1.独立看门狗,与窗口看门狗的差别
1. 差别1 : 窗口看门狗, 有上限 0x7F, 有下限 0x40 ,, 独立看门狗只有下限 0
2. 差别2: 时钟源不同, 独立看门狗:LSI
窗口看门狗 :APB1时钟 分频后得到时钟驱动
2.窗口看门狗配置过程
3.代码
头文件
#ifndef __MY_WWDG_H__
#define __MY_WWDG_H__
#include "stm32f4xx_wwdg.h"
#include "stm32f4xx_gpio.h"
void mywwdg_init(void);
#endif
.cpp 文件
#include "mywwdg.h"
void mywwdg_init()
{
NVIC_InitTypeDef NVIC_InitStruct;
// 使能看门狗时钟: RCC_APB1PeriphClockCmd();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
//设置分频系数: WWDG_SetPrescaler();
WWDG_SetPrescaler(WWDG_Prescaler_8);
//设置上窗口值:
WWDG_SetWindowValue(0x6f);
//开启提前唤醒中断并分组
NVIC_InitStruct.NVIC_IRQChannel = WWDG_IRQn ;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
//6清除提前唤醒中断标志位:防止提前进入中断函数中。
WWDG_ClearFlag();
WWDG_EnableIT();
// 使能看门狗:
WWDG_Enable(0X7F);
}
void WWDG_IRQHandler()
{
WWDG_SetCounter(0x5f);
WWDG_ClearFlag();
}
4.IIC 的通信协议
基础知识:l2C(Inter-Integrated Circuit)总线是一种由Philips公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线产生于在80年代,由于其简单性,2C总线被非常广泛地应用在EEPROM(指带电可擦可编程只读存储器)、实时钟、小型LCD等设备与CPU的接口中。
I2C总线是一种用于Ic器件之间连接的双向二线制总线,所谓总线,是指它上面可以挂多个器件,并且通个两根线连接,占用空间非常的小。
I2C总线有两根信号线,一根为SDA(数据线),一根为SCL(时钟线)。任何时候时钟信号都是由主控器件产生,读取I2c从控器的数据或向I2C从控器写入数据。l2C总线实现设备通信的框图如下:
5.IIC .的信号内容 (状态, 与信号)
1. 空闲状态 : I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。
2.起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
3.停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是—种电平跳变时序信号,而不是一个电平信号。
4. 应答信号: 当我们的主机把时钟信号拉高之后, 从机把数据总线的电平变为低电平, 主机收到这个低电平的信号。
5. 当我们的主机把时钟信号拉高之后, 从机把数据总线的电平变为高电平, 主机收到这个高电平的信号。
6.IIC 主机发送数据
发送数据的流程:
两种情况:
1. 主机发送 一个信号表明自己要发送数据给这个从机 (7 个地址)
2. 主机发送 一个信号表明自己要接收数据从这个从机(7个地址)这里。
数据格式:
1. 第一个 主句发送起始信号
2. 第二个发送 从机的7 为的地址信号 和一位的 读写信号(判断主机 收数据,还是接收数据)
3. 从机应答
4. 第一种情况: 主机发送数据从机应答, 第二种情况: 从机发送数据主句应答。
7.代码:
头文件:
#ifndef __MY_IIC_H__
#define __MY_IIC_H__
#include "stm32F4xx.h"
#define SCL_HIGH() GPIO_SetBits(GPIOB,GPIO_Pin_6)
#define SDA_HIGH() GPIO_SetBits(GPIOB,GPIO_Pin_7)
#define SDA_LOW() GPIO_ResetBits(GPIOB,GPIO_Pin_7)
#define SCL_LOW() GPIO_ResetBits(GPIOB,GPIO_Pin_6)
void IIC_Init(void);
//起始信号
void IIC_Start(void);
//停止信号
void IIC_Stop(void);
//发送应答信号
void IIC_Ack(void);
//接收应答信号
u8 IIC_Wait_Ack(void);
//发送非应答信号
void IIC_NAck(void);
//发送一个字节数据
void IIC_Send_Byte(u8 sendData);
//读取数据线的高低电平
u8 READ_SDA(void);
//输入输出
void SDA_IN(void);
void SDA_OUT(void);
#endif
.cpp 文件
#include "myii.h"
#include "stm32f4xx_rcc.h"
#include "mysystick.h"
// PB6---SCL PB7---SDA
void IIC_Init()
{
GPIO_InitTypeDef GPIO_InitStruct ;
//第一步:AHB1总线上的E组引脚时钟使能;(心脏开始跳动)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
//设置gpio结构体
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7 ; //控制哪一个引脚 PE8
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; // 设置引脚为输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //设置输出速度
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽方式
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //设置高电平还是低电平
//设置GPIO口寄存器数据
GPIO_Init(GPIOE,&GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);
}
//起始信号
void IIC_Start()
{
//设置输出模式
SDA_OUT();
//一开始两根线拉高,空闲
SDA_HIGH();
SCL_HIGH();
delay_us(2);
//数据线产生下降沿,低电平
SDA_LOW();
delay_us(2);
//把时钟线拉低
SCL_LOW();
}
//停止信号
void IIC_Stop()
{
//设置输出模式
SDA_OUT();
//一开始低电平 数据无效
SDA_LOW();
SCL_LOW();
//时钟线拉高 使在高电平的时候有上升沿
delay_us(2);
SCL_HIGH();
delay_us(2);
//产生上升沿
SDA_HIGH();
delay_us(2);
}
//发送应答信号
void IIC_Ack(void)
{
//先设置输出模式
SDA_OUT();
//时钟线拉低
SCL_LOW();
delay_ms(2);
//发送应答信号
SDA_LOW();
delay_ms(2);
//时钟线拉高,在高电平期间保持SDA稳定
SCL_HIGH();
delay_ms(2);
//拉低,数据线无效
SCL_LOW();
}
//发送非应答信号
void IIC_NAck()
{
//先设置输出模式
SDA_OUT();
//时钟线拉低
SCL_LOW();
delay_ms(2);
//发送应答信号
SDA_HIGH();
delay_ms(2);
//时钟线拉高,在高电平期间保持SDA稳定
SCL_HIGH();
delay_ms(2);
//拉低,数据线无效
SCL_LOW();
}
//发送一个字节数据
void IIC_Send_Byte(u8 sendData)
{
u8 i = 0;
//先设置成输出模式
SDA_OUT();
//时钟线拉低
SCL_LOW();
for(i = 0; i < 8;++i)
{
if(sendData& 0x80)
{
SDA_HIGH();
}
else
{
SDA_LOW();
}
sendData <<= 1;
delay_ms(2);
//时钟线拉高 开始发数据
SCL_HIGH();
delay_ms(2);
//数据发送完成后,时钟线拉低
SCL_LOW();
}
}
u8 IIC_Wait_Ack(void)
{
u8 count =0;
//设置输入模式
SDA_IN();
//数据线拉高
SCL_HIGH();
delay_ms(2);
//时钟线拉高
SDA_HIGH();
delay_ms(2);
//读SDA线高电平还是低电平
while(READ_SDA() != 0)
{
count++;
if(count > 250)
{
IIC_Stop();
return 1;
}
}
SCL_LOW();
//时钟线拉低
return 0;
}
//读取数据线的高低电平
u8 READ_SDA(void)
{
u8 val = 0;
val= GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7);
return val;
}
//输入输出
void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct ;
//第一步:AHB1总线上的E组引脚时钟使能;(心脏开始跳动)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
//设置gpio结构体
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 ; //控制哪一个引脚 PE8
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; // 设置引脚为输出
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //设置高电平还是低电平
//设置GPIO口寄存器数据
GPIO_Init(GPIOE,&GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_7);
}
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct ;
//第一步:AHB1总线上的E组引脚时钟使能;(心脏开始跳动)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
//设置gpio结构体
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 ; //控制哪一个引脚 PE8
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; // 设置引脚为输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //设置输出速度
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽方式
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //设置高电平还是低电平
//设置GPIO口寄存器数据
GPIO_Init(GPIOE,&GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_7);
}