发帖数

50

原创数

50

关注者

12

阅读数

9787

点赞数

4

蔡琰

  • 单片机学习之基础篇

    寄存器

    寄存器,是集成电路中非常重要的一种存储单元,在集成电路设计中,寄存器可分为电路内部使用的寄存器和充当内外部接口的寄存器这两类。内部寄存器不能被外部电路或软件访问,只是为内部电路的实现存储功能或满足电路的时序要求。而接口寄存器可以同时被内部电路和外部电路或软件访问,CPU中的寄存器就是其中一种,作为软硬件的接口,为广泛的通用编程用户所熟知。

    我们举例STM32的一个寄存器:

    1.jpg 

    1. 关于学习资料

    对于学习一款单片机而言,资料不需要很多,最主要的还是芯片的手册,手册里面会体现出你想要的,有的人忽视手册,想要通过某种捷径直接去跳过这一步,在这里我想说,除非你有一定的了解,有信心前面的过程不会出现问题,否则还是老老实实的去啃手册,下面我们来介绍下学习STM32F373CCT6这款单片机我们用到的文档:

    1.STM32F373_Reference_Manual》是 ST 出的官方资料,有 STM32F3的详细介绍,包括了STM32F3 的各种寄存器定义以及功能等,是学习 STM32F3 的必备资料之一。

    2.STM32F373xx》也是 ST 出的官方资料,有关于芯片引脚定义,模块功能概括以及芯片的电气属性等介绍,是学习 STM32F3 的必备资料之一。

    3. STM32F3 F4 系列 Cortex M4 内核编程手册》 则是对 上述资料的补充, 很多关于 CortexM4 内核的介绍(寄存器等) ,都可以在这个文档找到答案,该文档同样是 ST 的官方资料,专门针对 ST Cortex M4 产品。4. Cortex M3 M4 权威指南》则针对 Cortex M4 内核进行了详细介绍,并配有简单实例,对于想深入了解 Cortex M4 内核的朋友,此文档是非常好的参考资料。


    2. 关于学习方法

    首先你要有个实验平台,不管资料再多这些资料的来源依据还是数据手册,一定要自己去对着数据手册仔细研读,自己独立动手配置,在平台上去做实验。只有不断的实验你才能理解。当遇到问题时不要在第一时间去网上搜索答案,再去研读数据手册,解决不了的时候,再试图去网上参考借鉴一下其他朋友的案例。


    3. MDK5软件的使用

    3.1 STM32  官方 标准 固件库简介

    ST(意法半导体)为了方便用户开发, 提供了一套丰富的 STM32 固件库。 到底什么是固件库?它与操作寄存器有什么区别?这一节,我们将讲解 STM32 固件库相关的基础知识, 希望能够让大家对 STM32固件库有一个初步的了解。

    3.1.1  库开发与寄存器开发的关系

    固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道,向上提供用户函数调用的接口(API) ,最终操作的还是寄存器。

    51 的开发中我们常常的做法是直接操作寄存器,比如要控制某些 IO 口的状态,我们直接操作寄存器:

    2.jpg 

    我们写成十六进表示:P0 = 0xAA;

    而在 STM32 的开发中,我们同样可以操作寄存器:

    GPIOA->BSRR=0x0001;

    为了省却麻烦, ST(意法半导体)推出了官方固件库, 固件库将这些寄存器底层操作都封装起来, 提供一整套接口 (API)。

    比如上面的控制 BSRR 寄存器实现对某一引脚的电平控制,官方库封装了一个函数:

    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

    {

    GPIOx->BSRR = GPIO_Pin;

    }


    位操作

    C 语言位操作相信学过 C 语言的人都不陌生了,简而言之, 就是对基本类型变量可以在位级别进行操作。这里简单复习一下。我们讲解几种位操作符,然后讲解位操作使用技巧。

    运算符

    含义

    运算符

    含义

    &

    按位与

    ~

    取反

    |

    按位或

    <<

    左移

    ^

    按位异或

    >>

    右移

     

    1. 不改变其他位的值的情况下,对某几个位进行清0

    GPIOA-> BSRR = GPIOA-> BSRR & 0XFF0F;  //将第 4-7 位清 0

    不改变其他位的值的状况下,对某几个位进行置1

    GPIOA-> BSRRL = GPIOA-> BSRRL | 0X0040; //设置相应位第6位的值,不改变其他位的


    2. 移位操作

    GPIOx->ODR = 1 << 2; //1<<2 = 4 相当于把4给了ODR寄存器

    GPIOx->ODR = 4 >> 2; //4<<2 = 1 相当于把1给了ODR寄存器

    ~取反操作  //用来对一个二进制数按位取反,即0110

    GPIOx->ODR  = ~GPIOx->ODR


    3. ^按位异或 //若参加运算的两个二进制位值相同则为0,否则为1.

    GPIOx->ODR  = 0x05^GPIOx->ODR

    以上就是做单片机控制的基础知识,踏实学了可以节省时间和精力去做应用模块的逻辑和算法了。基础扎实了会让产品更稳定,不能模棱两可的设计,否则故障会意想不到的出现。


    收藏 0 回复 0 浏览 173
  • 回调函数的使用

    大家好!我是张飞实战电子蔡琰老师,今天给大家讲解回调函数的使用。

    回调函数(Callback Function)是程序中一种常用的函数调用方式。其特点是可以在下层软件模块(宏观上的被调用者)中,调用来自上层的软件模块(宏观中的调用者)中的函数,这和通常的调用顺序是相反的。

    程序调用的方式:

    软件模块的关系,从总体上看,有上层软件模块和下层软件模块之分。一般有三种调用方式:

    简单的同步调用

    带有回调的调用

    异步调用

    同步调用是最常用的调用方式,由上层模块调用下层模块。在调用过程中,上层模块将被阻塞,直至下层模块执行完毕并返回。在方向上,同步调用是单向的调用方式,如下图所示:

    图片1.jpg

    上图调用方式为A->B。即上层模块的函数A调用下层模块的函数B,在调用过程中函数A被阻塞,当函数B返回之后,函数A继续执行。在B执行过程中,A不能得到B执行的消息。同步调用是一种最简单的调用方式,在大多数的C语言库函数调用中,都使用这种方式。

    带有回调的调用方式是一种双向调用模式,在这种方式中,下层模块的函数在被调用的时候,将会调用上层模块的某个函数,如下图所示:

    图片2.jpg

    在带有回调的调用中,调用方式为A->B->C。位于上层模块的函数A调用下层模块的函数B,在B的执行过程中,将调用上层模块的函数C。在这里函数C被称为回调函数,它是被下层模块所调用的上层模块函数。B函数执行的过程中,可以通过调用C函数将信息返回给上层模块。对于上层模块,C函数至少有两个作用,其一是监视B的运行状态,其二是干预B的运行。在这种方式中,本质上的关系依然是上层调用下层,由于增加了回调函数C,这样可以在调用的过程中进行交互。

    异步调用一般基于消息或事件,下层模块接受上层模块的命令,当发生某个事件的时候,下层模块将调用上层模块的函数。异步调用方式一般基于回调函数的注册机制。异步调用如下图所示:

    图片3.jpg

    在异步的调用方式中,调用方式为A->B立刻返回,当某个事件发生后,进行D->C的动作。本来上层模块的A调用下层模块的B的时候,只是一个简单的同步调用,调用完后将立刻返回。在A->B的调用过程中,可以向下层模块注册某些信息,例如回调函数C,当下层模块的某个事件发生的情况下,调用上层模块的C函数。

    再来看下回调函数的作用:

    回调函数的表现形式是一个某种类型的函数指针,这个函数由上层的软件模块实现,将这个函数指针通过某种方式传递给下层的软件模块,由下层的软件模块在某个时刻调用这个函数。

    函数指针的本质是一个函数的地址,在32位的C语言系统中,本质上就是一个32位无符号的整型数。函数指针由上层软件模块到下层软件模块的传递方式可以是通过作为函数的参数传递,也可以是使用结构体的成员进行传递。调用回调函数的时刻一般有两种:一种是在上层模块调用的下层模块的函数中,直接调用回调函数;另一种是使用注册的方式,在某个事件发生的时候下层模块调用回调函数。


    收藏 0 回复 0 浏览 169
  • 单片机的时钟源

    大家好!我是张飞实战电子蔡琰老师,今天给大家分享单片机的时钟源


    在单片机中,比如我们常用的STM32是有五个时钟源的,分别是:HSI,LSI,HSE,LSE,PLL。


    这些时钟源都体现在时钟树,我们知道每个型号的单片机手册都有时钟树的展示,这样让我们能清楚知道应用到的外设是通过哪个时钟源分频或倍频得来的。我们以ST推出的STM32G030为例来看下:

    image.png

    1、HSI是高速内部时钟,RC振荡器,频率为16MHz。

    2、LSI是低速内部时钟,RC振荡器,频率为32KHz。

    3、HSE是高速外部时钟,可接晶体/陶瓷振荡器,或者接外部时钟源(Bypass模式),频率范围是4-48MHz。

    4、LSE是低速外部时钟,接频率为32.768KHz的石英或谐振器,或者使用旁路模式引入外部时钟源。

    5、PLL为锁相环倍频输出,其时钟输入源可选择为HSE、HSI。倍频可选择为1~8倍,但是其输出频率最大不得超过64MHz(注意单片机的最大频率)。


    我们看到LSI(32KHz)供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。


    当然我们看到RTC的时钟源还可以选择LSE,或者是HSE的32分频。当然选择哪个作为最终的时钟源就是通过寄存器来配置了。

    这个LSI(低速内部时钟)可以用于除Shutdown和VBAT模式之外的所有模式。


    系统时钟是可以提供绝大部分工作的时钟源,是可以通过LSE、LSI、HSE、PLL、HSI分频获得。系统时钟可以分频给到总线去分到各个外设上,还可以直接提供给外设,比如ADC和I2S。系统时钟、AHB总线的最大时钟可以是64MHz(单片机支持最大频率)。


    HSI时钟可以衍生HSISYS,HSISYS这个可以从Stop0和Stop1模式唤醒后被选为时钟源,也可以当做备份时钟源。


    I2C、UART、LPUART在Stop模式下如果探测到了从Stop模式下唤醒的序列则能够自动使能HSI16时钟。(HSI16时钟在Stop模式下保持关闭的状态,除非探测到了外设唤醒序列)


    HSE的时钟安全系统(CSS),自动检测到HSE失效时切换到HSI16。


    LSE的时钟安全系统适用于除了Shutdown和VBAT模式之外的所有模式,在复位状态下仍然有效。


    LSE可用于RTC, U(S)ARTs, LPUART, LPTIMs.

    PLL可以给到三路输出,是可以获得的最大频率不一样,给到的外设不一样,PLLPCLK是最大频率可以做到122MHz,可以给到ADC或者I2S。PLLQCLK最大频率是112MHz,是应用到定时器的。PLLRCLK最大频率是56MHz,主要是给到系统时钟。

    多个时钟源的好处是在选择时钟源的时候具有高度的灵活性,可满足功耗和精度的要求。


    许多独立的外设时钟允许在不影响通信波特率的情况下调整功耗,并在低功耗模式下保持一些外设有效。


    现在很多单片机都考虑到了低功耗,自然时钟也是其中很重要的部分了。


    对于应用外设时钟这块还是很重要的,需要会看时钟树,会对应用需要的时钟进行配置,这个就显得很重要了,比如想要高速时钟需要倍频,如果是低功耗需要分频,首先还是需要去看时钟的分布,才好再去应用的。




    收藏 0 回复 0 浏览 165
  • 白话文讲解STM32时钟树

    时钟就像是单片机的“心脏”,单片机正常工作离不开时钟的支持,下图是我们单片机的时钟树 ,它反映了单片机的时钟关系我们来详细描述一下时钟树的工作原理。
    1.jpg


        寄存器上电后有一个复位值,大家看我画红线的这个,这个是单片机上电默认使用时钟的配置线路默认使用的是内部默认的8M  RC振荡器有两条路可以选我们先看上面红色的第一条,到多路选择SW的时候,我们可以通过配置寄存器中的SW来决定HSI/PLLCLK/HSE哪一个输入信号从多路选择器通过,在默认的状态下SW选择的是HSI8M从多路选择器通过。


        通过了SW这个选择开关后,第一个是SYSCLK 一路朝上可以供I2C1选择时钟另外一个就是继续向后,通过AHB 这个方框,在这里我们可以配置寄存器选择这个8M是否分频默认是不分频 也就是经过这个方框后出来往后的还是8M,如果这里配置为2分频,方框出来后就是 4M 经过AHB分频出来后还是8M 这个8M 提供给了很多路大家可以从上面的图中看出来,那么继续向后是 APB 分频
        这里分了两个箭头指向,一个是朝上的给AHB总线 内核Memory  DMA内核定时器FCLK从这里我们可以看到 内核是8M时钟这个频率决定了单片机指令的执行时间,频率越小,指令执行速度越慢一路是向后给了APB分频器,这里可以配置你想要的分频系数,如果这里还是不分频出来的PCLK 还依然是8M,那么PCLK又给了 APB外设 还给了定时器、串口等外设。


    通过这个关系,我们可以清楚的知道,每个外设的工作频率,那可能就会有人问了,这有什么用呢?每个外设都需要时钟来提供振荡源来帮助完成工作,举个例子讲,比如说串口配置一个波特率,那么波特率(通信速率,表示每秒钟传送的数据的位数,即bit/s)是如何来配置呢,就是根据这个时钟频率来配置的,知道了时钟频率,厂家有一个计算公式,就能很容易的算出某一个波特率对应的寄存器值是多少。

    默认的我们知道了,M0支持最大48M内部RC振荡器只有8M,这个咋整呢?不要慌,我们继续往下看。


    2.jpg 

    既然HSI直接给SW多路选择器,不能到48M,那我不直接给通过SW了行不行,请看图中箭头处,HSI绕一下从 PLLSRC 多路选择器通过那么PLLSRC多路选择器也有两个选择可以通过寄存器配置,假设配置寄存器选择 HSI作为输入多路选择器输出后经过PREDIV分频器,假设 PREDIV 我们配置不分频这个分频器出来输入到PLL模块的时候还是8M


    3.jpg
    PLL模块起到 一个倍频的作用,大家可以看到方框里面是乘2 3...,如果这个时候我们配置寄存器设置PLLMUL6,那么出来的PLLCLK 48M,那么这个时候 SW多路开关选择 PLLCLK作为输入,后面出来的时钟就是48M了,再往后面就跟上面讲的情况一样了,可以自由去配置分频


    使用内部RC振荡器我们理解了,但是内部的振荡器往往会因为,精度低,受温度影响比较大等情况,不会被选择,这个时候工程师们就会选择使用外部晶振,外部晶振也是一样的配置方式,大家是否能根据上面讲的思路,配置出来呢?


    收藏 0 回复 0 浏览 159
  • 红外遥控原来这么简单!

    大家好!我是张飞实战电子蔡琰老师!今天给大家分享红外遥控接收。

    平时我们经常会用到遥控器,那么现在遥控器也分很多种类,有使用红外通信的,也有使用蓝牙,无线的等,今天我们来一起解码一下红外的工作原理。

    大家看现在图中的是2个红外对管,左边是发射端,右边是接收端,

    image.png

    遥控器上有一个红外发射二极管,发射红外数据信息,电视机上有一个红外接收管,接收红外信息,那么到底是怎么把数据从二极管中发送出去的呢?

    image.png

    如上图,遥控器发送之前要先进行编码调制,然后进行信号放大发射,接收设备需要先对这个信号进行解调,解调之后的信号送给单片机,单片机进行解码(分析是什么数据)。

    调制过程就是需要加上载波信号,中间加载了一个载波信号,发送的数据就是通过载波信号送出去的,对应的接收信号就需要对收到的载波信号进行解调处理了,即信号还原。

    image.png


    image.png

    一般情况下接收头,只能解调固定的一种载波频率信号,那遥控器的发送信号的载波频率要与接收头所用的频率一致,否则是没办法正确接收的。自然界中存在红外光,进行调制主要是为了避免一些干扰,以防止传输出错。下面我们一起来看看遥控器传输的协议编码规则。

    遥控器信号开始的地方有一段特殊长度的信号,这个我们叫它是引导码,引导码是9ms高电平+4.5ms的低电平,单片机只有结束到了正确的引导码,才可以开始接收后续的数据。

    image.png

    image.png

    image.png

    我们知道有效数据要么是0,要么是1,0或者1都是由一个固定的高电平+低电平组成,数据1: 0.56ms高电平+1.69ms低电平组成,数据0: 0.56ms高电平+0.56ms低电平组成,也就是说收到这样的一个高电平+低电平的数据就是认为收到有效数据了,再根据判断时间来区分是0还是1。通过分析出来0 1,再把这些0 1组合成一个有用的数据,然后进行处理执行动作,比如切换频道,关机、开机等。这样就是一个完成的遥控器发送,接收原理了。

    image.png

    上图是我们实测的一个遥控器解调后的波形中,你能分析出图中传输的数据吗?

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