SysTick

滴答定时器配置

1.配置

  • 使用库函数版本: STDLIB v3.5
  • 函数的声明: misc.c,core_cm3.h
  • 配置函数在库函数中的位置:
    • 时钟源配置:misc.c->SysTick_CLKSourceConfig()
    • 重装载配置:core_cm3.h->SysTick_Config
  • 结构体声明: core_cm3.h

2.Systick寄存器

  1. 系统滴答定时器是一个24位倒计时定时器,捆绑在NVIC中,用于产生SYSTICK异常(异常号:15),它由4个寄存器控制
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E3jc6tjw-1582033310940)(https://i.loli.net/2020/02/18/iGndXL9TKVCJHPI.png)]
  2. 滴答定时器配置过程:
    1. 配置时钟源: 0:外部时钟源:STCLK(HCLK/8),1:内部时钟源:FCLK(HCLK).配置分频系数
    2. 计算重装载值.(中断周期=重装载值*时钟源周期)
    3. 滴答定时器中断配置
      1. 中断优先级配置
      2. 滴答定时器中断使能
    4. SysTick使能
  3. SysTick寄存器(寄存器的详细信息在《stm32参考手册》中没有,在《ARM Cortex-M3技术参考手册》才有其相关介绍)
  4. 标准库函数解析:
    • core_cm3.h
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
   if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /*重载值超过24位,配置失败,返回0. */
   SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
   NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
   SysTick->VAL   = 0;                                          /* Load the ck Counter Value */
   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |                //设置SysTick时钟源内部时钟源
                    SysTick_CTRL_TICKINT_Msk   |  
                    SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
   return (0);                                                 /* Function successful */
}
  1. 滴答寄存器配置的参考网站
  2. 使用的滴[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BkJZ1miN-1582033547153)(https://i.loli.net/2020/02/18/iGndXL9TKVCJHPI.png)]答定时器编写延时函数

位带操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i4ZOwlwF-1582033310941)(https://i.loli.net/2020/02/18/WXxunfo4clZpsKT.png)]

1. 位带操作的意义

1MB = 0x0010_0000,位带区和位带别名区相差31MB(0x0200_0000)
实现对某GPIO口寄存器或SRAM内存中的某1bit直接写0或1.在Cortex-M3中,有两个区实现了位带,一个是SRAM中最低1MB的范围,一个是外设区最低1MB范围.把位带区的1bit膨胀成位带别名区(alias region)的32bit操作位带别名区的32bit相当于操作位带区的1bit.

2. 位带操作实现方式

  1. 知道目标寄存器的目标bit
  2. 根据计算公式计算出要操作bit所在的位带别名区地址
  3. 将别名区地址转换成指针类型便于操作

3. 代码操作

  1. 将比特转换成别名区地址
#define BITBAND(addr,bitnum) ( (addr & 0xF0000000)+0x20000000+((addr & 0xFFFFF)<<5)+(bitnum<<2) ) 

addr:包含目标比特的寄存器地址,bitnum:要操作的目标比特.(addr&0xF000_0000): 通过高位的不同区分出是SRAM的位带还是外设区的位带.0x0200_0000: 位带别名区相应相对应位带区的偏移量

这一步最后实现的效果就是将目标寄存器的目标比特位地址转成成对应位带别名区的地址,一个地址->一个地址.

  1. 将别名区地址转化成指针
#define MEM_ADDR(addr) *( (volatile u32 *)(addr) )

把目标bit的别名区地址存储在指针内,然后把地址转换成指针类型,从而通过指针操作可以直接对位带别名区地址进行读写操作

  1. 对前两部进行整合
#define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr,bitnum))

特别注意

  1. stm32内部位段操作原理的实质是把对别名区的地址的读写->映射成对相应的位的读写.这个操作直接在CACHE中完成原子操作,不需要CPU寄存器参与运算,所以运算速度很快.

  2. 别名区地址以字对齐,每个字只有最低四位有意义,访问别名区时,要把地址对齐到字的边界上.,必须避免对2200_0001,2000_0002…地址不是4的整数倍的地址的读写!!!

例如:
对2000_0000的读写被映射到对2000_0000所存字节的BIT0的读写.
对2200_0004的读写被映射到对2000_0000所存字节的BIT1的读写.
对2200_0008的读写被映射到对2000_0000所存字节的BIT2的读写.

  1. 位带操作参考网站
    位带操作详细解释
  2. 手册位置
    3.3 Memory map->3.3.2 bit banding

一些傻瓜问题

  1. 加入的头文件没用
    注意 #ifdef#ifndef.

一些名词的解释

1. HCLK: AHB Clock

C语言进阶

  1. volatile: 是一个类型修饰符与const一样,用于修饰被不同线程访问和修改的变量.volatile是指令关键字,能够确保本条指令不会因编译器的优化而省略,且要求每次读值.

  2. inline内联函数: 内联函数是指:当编译器发现某段代码在调用一个内联函数时,它不是去调用该函数,而是将该函数的代码,整段插入到当前位置。这样做的好处是省去了调用的过程,加快程序运行速度,但是因为把内联函数拷贝了很多份,所以程序大小也变大.
  3. #ifdef的使用
    #ifdef详细讲解

积累的经验

  1. 标准库函数中所有外设基地址的宏定义在stm32f10x.h中,并且把寄存器地址转换成了结构体指针.可以通过宏定义直接使用.
    SysTick_第1张图片[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dl4DT88F-1582033310943)([外链图片转存失败,源站可能有防盗https://i链机lol接上传(ic.1et/20/023/LheEd6nkaSfMPtj.png5978https://i.loli.net/2020/02/18/LheEd6nkaSfMPtj.png)])]

  2. keilC编译器不支持二进制表示.

  3. 无符号类型和0比较无意义.char位无符号字符型占8bit,signed char为有符号字符型.

  4. STM32 GPIO口初始化后输出电平为高电平.

  5. 5.注意LED灯点亮的顺序,应该是先亮后灭,因为如果是先灭后亮,那么在循环中上一次的灯就不会熄灭会一直亮着,因为管脚初始化之后就是输出高电平.

  6. 在对锁存器的GPIO口进行操作前要确保LE管脚是active的状态.

  7. 比赛时要注意的事项

    1. 新建好模板之后要确定能够烧录进去.
    2. 芯片选型要选STM32F103RB,FLASH是128KB.
    3. 在配置的时候,似乎锁存管教的LE管脚并不需要配置就是使用的高电平,所以可以不配置也依然可以正常使用LED灯,锁存芯片的管脚:要先PCout(9) = 0 然后 LE = 1;如果是LE=1 然后 PCout(9) = 0;GPIO会没有现象。锁存输入管脚:顾名思义,当LE=1时,锁存芯片读取GPIO管教电平输出.
    4. 直接操作寄存器,如果使用 GPIOD->ODR = 0x03像这样会把之前某一处设置的GPIOD->ODR的寄存器的值给覆盖掉了.而使用|=对于那些默认值不为0的寄存器是不能正常操作的.本身寄存器是有值的,所以当用|=0x3333_3333之后没有把寄存器变成想要的3333_3333而是变成了7777_77777;
    5. M74HC573锁存器
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W9nln5Fc-1582033310944)(https://i.loli.net/2020/02/18/os3zVBq1WtUP2Ep.png)]
      1. 芯片的output Enable(OE)是低电平有效,Latch Eable input(LE)是高电平有效.LE的管教是输出端口在LE高电平时锁存输入端口的电平,当LE为0时.输出端口随输入端口变化而变化.
      2. l:在LE由高电平(锁存)到低电平变化前,输入端口为低电平
      3. h:在LE由高电平到低电平变化前,输入端口为高电平.
  8. 工程可以正常使用的配置
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ALPv8RCX-1582033310945)(https://i.loli.net/2020/02/18/81gJmDHTGkqVAWN.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zHAGP0Np-1582033310945)(https://i.loli.net/2020/02/18/9nvfCqKiygIwSzF.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MfCHUamV-1582033310946)(https://i.loli.net/2020/02/18/9Sn4JFtOiVxDgZl.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6pl2iAAw-1582033310946)(https://i.loli.net/2020/02/18/pxGRmNFIDrMX5Q4.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bOybCebL-1582033310947)(https://i.loli.net/2020/02/18/Npz5BWi8mIPso9Z.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-As2Ta7eK-1582033310948)(https://i.loli.net/2020/02/18/TezdwU94n3Gm6fb.png)]

你可能感兴趣的:(蓝桥杯)