STM32开发日记010:位带操作和看门狗

1.位带操作

在51单片机中,可以很方便的对单个IO口进行写入操作,
51单片机中:
按位操作,真正操作的的是类似于我们STM32中的ODR寄存器或者IDR寄存器中的单个bit。

p1.1=0;拉低
p1.1=1;拉高

在STM32单片机中外设地址部分:
外设的基地址:0x4000 0000
外设地址范围:0x4000 0000–0x4010 0000
0x4000 0000–0x4010 0000包含了我们所有的外设
以上外设地址保存的位置,我们成为位带区域
位带别名区:

为了模仿51单片机的操作,引入了位带别名区,位带区中的1Byte(字)对应别名去的4Byte。
STM32的单片机是32位,那么处理器处理速度最快的的话,就是一次处理32位的数据最快的,
在这里插入图片描述

单片机中都是按照字节寻址,一个地址(32位)对应1个字节,在位带区中的一个字节,在别名区就是4个字节,就是因为字节对齐的原因。

位带区域                                            别名区域
0x4000 00001字节)                             0x4200 0000(4字节)
0x4000 0001                                      0x4200 0004
0x4000 0002                                      0x4200 0008

A端口基地址:

0x4000 0000+0x10000+0x0800=0x4001 0800

A端口的ODR寄存器:

0x4001 0800+0x0c=0x4001 080c

A端口的IDR寄存器:
0x4001 0800+0x08

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) //addr--ODR或者IDR的基地址 bitnum--第几个IO口
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 

#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n) //

分析部分:

((addr & 0xF0000000)为了获得外设的基地址--0x4000 0000
(addr & 0xF0000000)+0x200 0000--别名区的基地址--0x4200 0000
(addr &0xFFFFF)<<5或者(addr &0xFFFFF)*8*4 将位带区的地址膨胀到别名区,此时addr还是IDR或者ODR的基地址
(bitnum<<2)或者(bitnum*4)--具体操作的IO偏移的位置,在别名区需要乘以4

位带源码部分:

//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

2.看门狗(独立看门狗)

在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成各种寄存器和内存的数据混乱,会导致程序指针错误,不在程序区,取出错误的程序指令等,都有可能会陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续正常工作,导致整个系统的陷入停滞状态,发生不可预料的后果。
看门狗,又叫 watchdog,从本质上来说就是一个定时器电路,一般有一个输入和一个输出,其中输入叫做喂狗,输出一般连接到另外一个部分的复位端,一般是连接到单片机。 看门狗的功能是定期的查看芯片内部的情况,一旦发生错误就向芯片发出重启信号。看门狗命令在程序的中断中拥有最高的优先级。
在这里插入图片描述

功能描述:

计数器计数方向:从上到下(从阈值开始,到0结束)
在这里插入图片描述

0Xfff递减计数,到0,如果还是没有喂狗,那么程序就要复位。
正常情况下,程序完整的执行一次的时间,假如正常情况程序执行一次,需要200ms,那么看门狗的计数时长,就需要大于200ms,那么我们就可以设置看门狗的计数时长为大于200ms,但是别写大于太多,300ms 400ms。

独立看门狗整体框图

在这里插入图片描述

时钟分频

在这里插入图片描述

void IWDG_Init(u8 prer,u16 rlr) //prer--4  rlr --625
{    
     IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  //使能对寄存器IWDG_PR和IWDG_RLR的写操作
    
    IWDG_SetPrescaler(prer);  //设置IWDG预分频值:设置IWDG预分频值为64
    
    IWDG_SetReload(rlr);  //设置IWDG重装载值
    
    IWDG_ReloadCounter();  //按照IWDG重装载寄存器的值重装载IWDG计数器
    
    IWDG_Enable();  //使能IWDG
}

注意:
debug调试代码的话,一定要先将看门狗注释,否则会一直复位,导致调试失败

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值