发帖数

50

原创数

50

关注者

12

阅读数

8744

点赞数

4

蔡琰

  • MCU低功耗设计注意要点

    随着便携式移动设备,各种穿戴设备的兴起,我们不得不关注设备的功耗问题,因为这些设备都具有一个特征:使用电池系统供电,一块线路板上跟功耗相关的单元电路可能有很多,今天我们来谈谈关于MCU的低功耗问题。


    谈到这个问题,首先得选用一款低功耗的MCU,一般MCU的功耗,在其对应参考手册的电器属性章节都会有说明,其次我们在使用MCU低功耗时经常会出现实际功耗理论功耗偏差较大,遇到这样的情况,需要仔细检查以下几点


     
      1、关闭外设时钟
      时钟就相当于是人的心脏一样,外设模块的正常工作不能脱离时钟。对于大多数的MCU,外设模块都一个时钟控制开关,只要打开外设时钟,就可以正常使用该外设了,当然,该外设也就会产生相应的功耗;如果用不到这个外设一定要记得把这个外设时钟关闭,降低功耗


      2、调整时钟频率
      一般我们使用单片机的时候,都喜欢上来就把时钟频率调到最高这样的优点是程序的执行速度快了,因为周期T = 1/F,一般我们进行频率调整都使用的是单片机内部的PLL倍频模块,把一个输入很低的频率倍频到很高的频率,一方面倍频的模块会增加功耗,另一方面时钟线上的对应的外设模块工作频率增加了,功耗也会相应的变大。你会看到,一般低功耗模式下,单片机的工作频率很低很低,所以考虑功耗一定不要忘记考虑时钟频率


      3、注意IO口的电平状态

    注意你没有使用的IO口部分的状态,以及IO口内部的上拉或者下拉的情况,这个也会积少成多,增加功耗的浪费。另外从本质上讲,我们不仅仅是只关注空闲的IO状态就罢了,对于使用的IO口,我们也需要考虑它们在正常工作时的一个状态,联合外围电路一起考虑,效果会更好一些。比如说我们需要点一个LED灯,如果单片机IO口一直输出一个高电平对应点亮LED,那我们是不是可以换一种思路,单片机输出低的时候对应LED亮呢?这样积少成多就能省下一部分功耗。


     4、断开仿真器等测试工具

    我们在测试的时候,通常会连接一些测试的工具,来辅助调试,有可能这些辅助的调试工具都是由线路板供电的,可能你会误认为把这部分功耗当成MCU的功耗,当然这里不仅仅是要关注测试的工具带来的功耗,而且你还需要关注你的测试方法,很有可能你的测试方法不对或者测试工具的本身也会有功耗。


      
        MCU的低功耗设计是一个细致活,要养成良好的习惯,每加一个外设功能模块,对应的外设带来的功耗我们可以测试,当前增加功能带来的功耗增加量,包括静态下的模块功耗,正常融入系统后工作时的功耗,随时掌握模块动态我们不仅要考虑内部的时钟状态、时钟频率,还需要考虑IO与外围电路的配合状况等等,通过调整电路的工作方式来减小一部分功耗。当然关于功耗可不止文中的几点,你还知道有其它什么原因影响MCU自身功耗吗?可以留言来跟大家一起分享哦!

    收藏 0 回复 0 浏览 88
  • STM32中SystTick是个啥?咋用?

    Cortex-Mx内核内部包含了一个SysTick定时器, SysTick 是一个24 位的倒计数定时器, 当计到0 时, 将从RELOAD寄存器中自动重装载定时初值。只要不把它在 SysTick 控制及状态寄存器中的使能位清除,就永不停息。SysTick 在《STM32xx 中文参考手册》里面基本没有介绍,其详细介绍,内核编程手册中 在工程中我们将STM32F373为例,为SysTick配置1ms,利用1ms中断处理系统任务。下面我们介绍下寄存器:

    下图是SysTick定时器的4个寄存器概括,我们介绍部分使用的寄存器:

    1.jpg 

    SysTick控制和状态寄存器

     

    2.jpg 

    这个寄存器的EBNALE(0)SysTick的使能位,TICKINT(1)为设置是否产生中断,CLKSOURCE(2)为时钟选择,当为1 AHB时钟不分频,为0AHB时钟8分频。当然我们选择使能定时器,产生中断,并选择AHB 8分频假如系统时钟为72M,即可获得 72/8 = 9MSysTick时钟频率。使能SysTick并产生中断,8分频时钟,代码如下:

                     SysTick->CTRL = (0<<2) | (1<<1) | (1<<0);

    SysTick重装载值寄存器

     3.jpg


     

                         该图来自数据手册中断和事件章节

    5SysTick重载计数值寄存器RELOAD([23:0]),从该介绍我们可以得出结论,SysTick的计数方式为向下计数,也就是从RELOAD([23:0])值向下递减,当减到0的时候产生标志位,这个时候会重新装载该寄存器值,循环执行上面的步骤。那麽我们可以利用这个功能做一个1ms的定时器,我们已经配置系统时钟为72M,使用系统时钟的8分频(9M)作为SysTick定时器的时钟,也就是说时钟周期T = 1/9M(ns),SysTick1需要1/9M(ns),我们定时1ms那麽重载寄存器的值为 1ms/(1/9M(ns))-1 = 8999(注意这里要进行单位换算),这也就是我们的重装载值,下面给出具体代码配置,其中使能等操作包含在SysTick_Config();函数里面。配置代码如下:

                             SysTick->LOAD = 8999;

    单个寄存器讲完了我们总结一下综合起来让SysTick工作起来,我们把SySTick的配置单独做成一个函数如下:

     

    Void SysTick_Init(void)

    {

       /*

       第一步:装载值

       第二步:使能SysTick并允许中断,8分频时钟

    第三步:设置SysTick优先级

    */

    SysTick->LOAD = 8999;

    SysTick->CTRL = (0<<2) | (1<<1)  | (1<<0);

    NVIC_SetPriority (SysTick_IRQn, (1<<4) - 1);

    }

    我们用库函数表示为:

    4.jpg 

        对于官方库函数的查找我们可以使用《stm32f37x_dsp_stdperiph_lib_um.chm》这文档,想要找某一方面的函数在里面直接搜索就可以,具体的使用方法我们下面仔细介绍。

    收藏 0 回复 0 浏览 85
  • 看完这篇,SPI其实也很简单嘛

    首先我们来简单介绍一下SPISPI是串行外设接口(Serial Peripheral Interface)简单来讲就是它一种高速的,全双工,同步的通信总线


    那么被各种总线搞的晕头转向的人来说就会问了,为什么要弄那么多种总线?太难了。一会I2C,一会SPI;一会内部总线,一会外部总线。


    碰到总线这样的字眼,千万别急,通过接触你会发现都有各自的特点,通过实践了你才会真正理解这些总线的用途,那么我们今天就来聊一聊SPI。


    下面我们来看一下SPI的框图,我们从框图上来介绍SPI通信的原理

    1.jpg 

    1. SPI传输需要有一个时钟因为他是同步通信所以连接引脚有串行时钟SCK

    2. SPI以主从方式工作,通常有一个或者多个从设备连接。所以MOSI,M是主机,S就是从机,从机输入,所以叫MOSI,I就是input输入的意思,那么MISO也是一样的原理。

    2.jpg 

    3. NSS就是片选,是SPI从设备是否被选中的,只有片选信号为预先规定的使能信号时(高电位或低电位),对此 SPI 从设备的操作才有效。如果从机没有被选中,主机发送数据从机是不会接收的。

    4. Rx FIFO,Tx FIFO:发送缓冲和接收缓冲,当高速通信的时候,数据来不及处理就可以放在缓冲区里面,可以节省一定的时间去处理其他事情。

    5. CRC controller:CRC校验,是一种数据检测方式。

    6. Communication controller:SPI的主控模块,从框图中我们得到一些重点信息,就是关于寄存器的配置信息。时钟输出波特率受BR[2:0]3个位来控制。


    以上就是单片机整个的SPI通信的架构,只有这些配合工作才能实现SPI通信。单片机SPI一般作为主机工作,那么参数配置就需要从机的一些信息了。那么看到这里大家可能觉得这不算讲了SPI啊,我还不懂怎么应用啊,没关系,上面只是简单介绍,知道基本信息了再去实现不就容易多了嘛。

    首先既然有时钟,那么就存在时钟极性的问题,既然有从机,那么可以根据从机的时钟极性来设置主机的,保持一致就好了,相当于相约好规则。


    SPI的时钟极性(哪种电平状态是有效的):

    3.jpg 

    CPOL0的时候,空闲状态不传输数据的时候是低电平,CPOL1的时候,空闲状态是高电平两种时钟极性是相反的

    其次时钟频率,波特率表示每秒钟发送多少位数据,可以根据波特率计算发送一位需要的时间。波特率由主机决定。

    接着就是时钟相位,也就是时钟信号SCK的第一个边沿出现对应位置在数据传输周期的开始位置还是中央位置。是不是有点绕,那看图说话,直接理解了。


    4.jpg 

    上面是开始位置,下面是中间位置,注意是第一个时钟信号的边沿啊。

    这里还要注意就是时钟极性和相位主从机必须设置一致(如果从机是不可编程的,那么要根据从机时序决定)

    那么对于从机来说是不是还要看个时序图,那什么是时序图?

    就是根据时间做不同的动作,就是时序图会把大家搞晕吧。我们来看一个时序图:

    5.jpg 

    根据上面对单片机SPI的分析,拿到这个从机的时序图你能分析出一些什么呢?

    如果根据这个时序图让你来做模拟SPI通信,你是否可以实现呢?(平时设计项目或产品碍于各种问题不得不用普通管脚实现SPI通信,这是很常见的)


    收藏 0 回复 0 浏览 79
  • 一文带你读懂ARM文字池

    说到文字池,首先第一个问题:什么是文字池?文字池又叫literal pool,它的本质就是ARM汇编语言代码节中的一块用来存放常量数据而非可执行代码的内存块。


    那为什么要使用文字池呢?当想要在一条指令中使用一个 4字节长度的常量数据(这个数据可能是内存地址,可能是数字常量)的时候,由于ARM指令集是定长的(ARM指令4字节或Thumb指令2字节),就无法把这个4字节的常量数据编码在一条编译后的指令中。此时,ARM编译器(编译C源程序)/汇编器(编译汇编程序) 就会在代码节中分配一块内存,并把这个4字节的数据常量保存起来,之后,再使用一条指令把这个4 字节的数字常量加载到寄存器中参与运算。 C程序中,文字池的分配是由编译器在编译时自行分配安排的,但是,汇编程序时,开发者可以自己进行文字池的分配,当然如果没有自己分配汇编器会代劳。不管何种情况,这不影响我们来了解学习一下文字池的知识。


    LDR Rd,=const 伪指令可在单个指令中构造任何 32 位数字常数。 使用此伪指令可生成超出MOVMVN指令范围的常数。LDR 伪指令可为特定的常数生成最高效的单个指令:如果可以用单个MOVMVN 指令构造该常数,则汇编器会生成适当的指令。如果不能用单个MOVMVN 指令构造该常数,则汇编器会执行下列操作:将该值放入文字池中生成一个使用程序相对地址的 LDR 指令,用于从文字池中读取该常数。说的通俗一点,如果LDR Rd, =const能够被转换成MOV 或者MVN指令,则汇编器将转换成它成为相应的指令,如果不能被转换,则汇编器会将value存放在文字池中,并且产生一个LDR指令操作。


    汇编器默认把文字池放在每一个代码节的末尾处。代码节的末尾的确定或者是由汇编源文件尾部的指示符END确定或者由相邻代码节的起始行AREA确定。在大的代码节中(通俗理解为这个节中的代码量比较大),默认文字池在最后,可能与代码节中一条或多条LDR伪指令的距离很远,可能超出LDR伪指令操作数的寻址范围。


    当伪指令是32位时,在ARMThumb代码中,必须小于4K字节,文字池常量数据的位置可以是在伪指令的前面,也可以是在伪指令的后面当伪指令是16Thumb指令时,必须小于1K字节,且文字池必须位于伪指令的后面。


    LDR  Rd, =const 伪指令需要一个文字池来存放立即数常量时,汇编器检查已经存在文字池中是否有相同的常量并且检查文字池是否在伪指令允许寻址范围内。如果条件满足,汇编器引用这个满足条件的常量,否则汇编器会尝试把该常量值放到文字池未用的空间中。如果空间地址超出伪指令的寻址范围,汇编器会产生一条错误信息。这种情况下,程序员必须得自己用指示符LTORG在代码中设置增加一个文字池。指示符LTORG放在导致错误的伪指令后面,并且位于伪指令LDR的有效寻址范围内(一般节的代码量不是特别大的情况下,可以放于中间位置)而且要保证设置的这个文字池,处理器执行代码的时候不会执行到这个地址。 它们应放在无条件跳转指令的后面,或者放在子例程末尾处的返回指令的后面。


    应用举例如下:

    Fun1
        LDR R0, =0X12345678
        ADD R1, R1, R0
     
       
    BX  LR    ;子程序返回
        LTORG    ;声明文字池
    ,存储0x12345678

    POOL  SPACE  20
     
    好了,关于文字池,本片文章就讲到这里了,大家有不明白的地方可以留言提问哦,谢谢大家。

    收藏 0 回复 0 浏览 75
  • 8脚51单片机DIY时间显示+闹钟技术分享(一)


    最近因为家里闹钟被小朋友摔坏了,所以想着买来买去还是没什么新意,不如自己做一个,这样不是更有意义吗?那就开始吧,想着自己做就可以用最小资源来实现最大功能了,然后开始查找需要的芯片资料,平时时间显示我们最起码要有小时和分钟吧,那么最起码要四位数码管了,还要有按键来调整时间吧,那么对IO口的管脚就开始有要求了,虽然是时钟显示,但是想来还是觉得不想因为节约管脚来把按键变少再去处理组合按键或者长按的按键。然后就开始各种查资料,后来找到一款很好的芯片,I2C通讯,直接可以实现4位数码管和四个按键的处理(当然这我只用到四个按键,其实这款芯片可以实现同时进行28键的键盘扫描),哇,这也太好了吧,迫不及待上图分享给大家了,就是下面这款:

    图片9.jpg


    功能好到真的跪了太好用了,好用到没朋友啊。因为这款芯片我太喜欢了,我会把这个芯片的数据手册放在附件,有兴趣的可以下载看看,真的好用还省去很多IO口。

    选到这款芯片,那单片机选型就自由了太多了,幸福感瞬间提升了,自己做时钟,要有个DIY的感觉,所以我选择把数码管全部换成LED(主要还有成本低哦),还有跟别人的东西不一样的感觉吧。然后既然我要做时间显示那么我就要选个时钟芯片的,既然显示和按键的选择了一个芯片实现,并且还是一个I2C接口,那同样时钟芯片我也选择了一款I2C通信的,那这样两个芯片用单片机的两个管脚就够了,是不是很省呢。既然要时间显示,如果单纯的时钟是不是很单调呢,最起码还要有个小闹钟吧,所以选择了一款带闹钟的时钟芯片,并且是I2C通信的,那这样时钟芯片也选好了,既然有闹钟,我就要加个蜂鸣器让它时间到了叫出来啊,不然怎么叫闹钟呢,这里我除了想到让闹钟报时滴滴的叫,还想到可以通过给蜂鸣器不同的频率让它唱歌呢,这里蜂鸣器我选择了一款无源蜂鸣器,这样蜂鸣器就只占用单片机的一个管脚也够了啊。现在的产品大多都是USB供电的,我也选择USB供电就可以了。到现在就只用了单片机的三个管脚,这样我就可以选择51STC8G1K08A)单片机中8脚的就够了。那么想到这些觉得有些意思了,那我就可以慢慢来实现了。

    其实别看我选的这些比较常用,还是挺简单的,这个看起来还是很容易实现的,起初我也这样想的,然而过程中并不是想象的那么顺利,还是踩了很多坑的。因为每个芯片都是有不同的特点,技术资料难免一次就能读透,还有就是会有点盲目的自信导致过程会有点曲折,所以还是要脚踏实地点好吧,我的曲折过程都会分享给大家,大体的器件选型好了,怎么实现呢,怎么做成我想要的东西呢,这个过程莫急,慢慢看我展示,主要会给大家分享避坑。

    后面就开始设计原理图和PCB了,最后产品出来才开始程序的实现,每个过程都好玩又有收获的,如果大家也感兴趣的话就持续关注我这个DIY的实现过程吧。随时欢迎大家跟我来探讨,也让我可以开阔下思路,或许下个小玩意更有意思呢。


    收藏 0 回复 0 浏览 73
×
蔡琰