DAY7-串口蓝牙,看门狗和RTC

202 阅读3分钟

3.代码实现

(1)起始信号和模块响应

0

(2)读一位数据

0

(3)读取温湿度

//读1个字节
u8 dht11_read_byte(void)
{
    u8 i,dat = 0;
    
    for(i=0;i<8;i++){
        dat |= dht11_read_bit()<<(7-i);//高位先出
    }
    
    return dat;
}
​
//读取温湿度数据
//返回0表示正常,返回非0表示失败
//temp,humi为输出参数,输出温湿度
int dht11_read_data(u8 *temp,u8 *humi)
{
    u8 i,buf[5] = {0};
    
    //发送起始信号
    if(dht11_check()==0){
        //读取40bit数据
        for(i=0;i<5;i++){
            buf[i] = dht11_read_byte();
        }
        
        //判断校验和
        if(((buf[0]+buf[1]+buf[2]+buf[3])&0xff)==buf[4]){
            *temp = buf[2];
            *humi = buf[0];
            return 0;
        }
    }
    
    return -1;
}

练习:

为串口命令添加读取温湿度的操作,温度>28时,D1亮报警,<=28,灭

湿度>70时,D2亮报警,<=70,灭

二十.串口蓝牙

串口蓝牙是一个蓝牙模块,内部有蓝牙芯片和程序,可以进行蓝牙通信,同时提供一个串口接口,通过串口配置蓝牙模块进行数据收发。

0

1.使用串口3连接蓝牙模块

0

2.手机上安装蓝牙调试器

0

3.初始化串口并配置蓝牙

(1)配置

从蓝牙模块的说明手册上查询模块默认的串口波特率,将串口3配置成和蓝颜模块的波特率一样(9600bps or 115200bps)。

蓝牙模块可以通过AT指令进行配置(波特率,广播名,版本,连接....),发送AT指令时不能连接蓝牙模块

"AT+NAME\r\n" -------- 查询蓝牙广播名
"AT+NAMExxx\r\n" -------- 设置蓝牙广播名

注意:如果是HC的蓝牙模块(带按钮的),需要按住按钮通电才进入AT模式(LED慢闪),默认是透传模式(LED快闪),AT模式波特率固定38400bps

"AT+NAME?\r\n" -------- 查询蓝牙广播名
"AT+NAME=xxx\r\n" -------- 设置蓝牙广播名
"AT+UART?\r\n" -------- 查询透传波特率

(2)设置广播名

将蓝牙模块设置为自己的名字,改名的代码只执行一次,之后注释掉重新烧写程序

0

改完名后重新烧写不改名的程序,重启蓝牙模块。

(3)使用蓝牙调试助手连接蓝牙模块,发送信息

0

练习:

配置蓝牙模块,修改成自己的名称,实现通过调试器的按键和文字发送信息到开发板

二十一.看门狗

1.概念

单片机构成的嵌入式产品,运行环境各种各样。所处的环境中可能有比较恶劣的情形(强电磁场,极端温湿度......)。

由于外接干扰,可能导致单片机内部数据混乱(内存数据,寄存器数据),程序运行出错,导致程序跑飞或者死循环,程序正常运行就会被打断,这种情况需要纠正。

看门狗的作用就是周期性查看芯片的运行情况,一旦芯片发生错误看门狗就会发送复位信号,让系统复位,使系统恢复正常运行。

2.原理

看门狗本质上是一个定时器,当看门狗定时器超时时,可以选择向芯片发送复位信号,正常情况下不能让看门狗超时,可以通过周期性地重置看门狗定时器的计数值来防止看门狗超时,这种操作就做喂狗。如果程序跑飞或者进入死循环,不执行喂狗的代码,看门狗定时器就会超时,导致系统复位。

0

3.看门狗的分类

看门狗分为内部看门狗和外部独立看门狗

内部看门狗使用芯片本身的时钟和电源,如果芯片异常导致看门狗异常,导致看门狗的作用弱化。

独立看门狗使用独立的时钟和电源,不会受到芯片本身异常的影响,监控效果更好。

4.stm32的独立看门狗

原始时钟使用的是低速内部振荡时钟 ------- LSI RC -------- 32KHz

0

stm32的看门狗寄存器具有写保护功能,操作修改寄存器之前必须关闭写保护

解除写保护:IWDG_KR =====> 0x5555
启动看门狗:IWDG_KR =====> 0xcccc
喂狗:IWDG_KR =====> 0xaaaa(自动打开写保护)

5.stm32f407看门狗的库函数实现

工程中加入独立看门狗的库函数源代码文件

0

(1)取消看门狗寄存器的写保护

IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);

(2)设置看门狗的预分频系数和初始计数值

void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);
//参数就是分频系数的值
@arg IWDG_Prescaler_4: IWDG prescaler set to 4
  *            @arg IWDG_Prescaler_8: IWDG prescaler set to 8
  *            @arg IWDG_Prescaler_16: IWDG prescaler set to 16
  *            @arg IWDG_Prescaler_32: IWDG prescaler set to 32
  *            @arg IWDG_Prescaler_64: IWDG prescaler set to 64
  *            @arg IWDG_Prescaler_128: IWDG prescaler set to 128
  *            @arg IWDG_Prescaler_256: IWDG prescaler set to 256
  
void IWDG_SetReload(uint16_t Reload);
//参数就是初始值(12位)//比如将周期设置为1s
IWDG_SetPrescaler(IWDG_Prescaler_32);//1KHz
IWDG_SetReload(1000);//1s    

(3)将重装载值放入计数器(喂狗)

void IWDG_ReloadCounter(void);

(4)启动看门狗

void IWDG_Enable(void);

6.窗口看门狗

窗口看门狗常用来保证某个操作必须在指定的事件范围内完成。基本原理类似于普通看门狗,但是对喂狗时间进行了限制。

0

二十二.RTC(实时时钟)

1.概念

RTC叫实时时钟,是芯片中用于记录具体时间的硬件

由于计时操作需要一直运行,永不停歇,因此RTC需要独立的电路,单独供电,使用独立时钟源。

0

0

0

stm32f407的RTC是一个独立的定时器,属于一种BCD码(用十六进制形式表示十进制)的定时器/计数器,提供日历时钟(年月日星期时分秒)和闹钟功能。‘

3.stm32的RTC框图

0

3.RTC配置的注意事项

(1)RTC寄存器默认开启写保护,写寄存器之前必须关闭写保护

1.将电源控制寄存器(PWR_CR)的DBP位置1
2.往RTC写保护寄存器(RTC_WPR)写入密钥:0xCA 0x53

(2)RTC的初始化

当初始化完成之后,RTC开始计时

4.RTC的库函数编程实现

工程中加入RTC(实时时钟)和PWR(电源控制)的库函数源代码文件

0

(1)使能PWR时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);

(2)使能RTC的寄存器访问

PWR_BackupAccessCmd(ENABLE);

(3)使能LSE,选择LSE作为RTC的时钟源

RCC_LSEConfig(RCC_LSE_ON);
//等待LSE就绪
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)!=SET);
//选择LSE作为RTC时钟源
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

(4)使能RTC的时钟

RCC_RTCCLKCmd(ENABLE);

(5)关闭RTC的写保护,等待就绪

RTC_WaitForSynchro();

(6)初始化RTC的分频系数和时间格式

ErrorStatus RTC_Init(RTC_InitTypeDef* RTC_InitStruct);
//传入RTC初始化结构 ----- 1Hztypedef struct
{
  uint32_t RTC_HourFormat;   /*!< 小时格式 12/24 @ref RTC_Hour_Formats */
  
  uint32_t RTC_AsynchPrediv; /*!< 异步分频系数(尽量大) lower than 0x7F */
  
  uint32_t RTC_SynchPrediv;  /*!< 同步分频系数 lower than 0x7FFF */
}RTC_InitTypeDef;

(7)设置初始日期和时间

//设置时间
ErrorStatus RTC_SetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
参数:
    RTC_Format - 时间格式 RTC_Format_BCD
    RTC_TimeStruct - 时间结构体
    
typedef struct
{
  uint8_t RTC_Hours;    /*!< 小时 */uint8_t RTC_Minutes;  /*!< 分钟 */
  
  uint8_t RTC_Seconds;  /*!< 秒钟 */uint8_t RTC_H12;      /*!< 上午/下午 @ref RTC_AM_PM_Definitions */
}RTC_TimeTypeDef;
​
//设置日期
ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
参数:
    RTC_Format - 日期格式 RTC_Format_BCD
    RTC_DateStruct - 日期结构体
    
typedef struct
{
  uint8_t RTC_WeekDay; /*!< 星期 @ref RTC_WeekDay_Definitions */
  
  uint8_t RTC_Month;   /*!< 月 @ref RTC_Month_Date_Definitions */uint8_t RTC_Date;     /*!< 日 */
  
  uint8_t RTC_Year;     /*!< 年 比如:0x22 */
}RTC_DateTypeDef;    

f;

(8)获取时间

void RTC_GetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
void RTC_GetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);

注意:可以通过RTC的备份寄存器实现只对RTC初始化一次

修改和读取备份寄存器:

void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data);
uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR);

作业:

完善蓝牙命令的代码,实现将温湿度,距离,可燃气体状态获取到手机。