突击蓝桥杯嵌入式(五)——EEPROM、RTC时钟、PWM输出和捕获和点灯改进版
一、PWM捕获频率和占空比
PWM捕获,首先我们看新板子上的2个信号发生器 分别占用PB4和PA15
然后我们配置CUBEMX,先选中PB4,TIM_CH1.
然后左面选择定时器3,选择PWM Input on CH1,时钟源选择内部时钟
配置预分频,然后开启定时器3终端。
然后配置时钟80MHZ,生成代码,然后我们介绍一下怎么获取占空比和频率。
先开启中断:
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
然后请上我们的主角
__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim); //捕获中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
static uint32_t ic1_value;
static uint32_t ic2_value;
if(htim->Instance == htim3.Instance) //当触发定时器3时
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//通道一
{
ic1_value = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
feq_r39 = 1000000/ic1_value;
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
}
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)//通道二
{
ic2_value = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
duty_r39 = ic2_value*100/ic1_value;
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
}
}
}
二、点灯改进版
void LED_Disp(uint8_t uc_led) //uc_led 对应灯的位数,例如0x55就是让第0 2 4 6号灯亮起 0101 0101
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|
GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,uc_led<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
三、RTC时钟
CUBE配置,开启时钟,选中RTC时钟,然后将上面2个都勾选,之后填入年份日期等信息
时钟树配置
//定义接受变量
RTC_TimeTypeDef TIME;
RTC_DateTypeDef DATE;
void RTC_Proc()
{
if(uwTick - uwtickRTC_Speed < 100) return;
else uwtickRTC_Speed = uwTick;
HAL_RTC_GetTime(&hrtc,&TIME,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&DATE,RTC_FORMAT_BIN);
}
//之后调用结构体就可以取出数值
void LCD_Proc()
{
sprintf((char *)str," %d. %d. %d ",DATE.Year,DATE.Month,DATE.Date);
LCD_DisplayStringLine(Line3,str);
sprintf((char *)str," %d. %d. %d ",TIME.Hours,TIME.Minutes,TIME.Seconds);
LCD_DisplayStringLine(Line4,str);
}
四、EEPROM
EEPROM分为以下几步:
1.添加i2c文件
资料包里有,把i2c_hal.c放到工程Core里面的Src,把i2c_hal.h放到Inc里面。
2.配置CUBEMX
把PA6PA7设置成output模式。
3.进入工程,
添加i2c_hal.c,写头文件,准备写代码。
4.写代码
首先我们要编写i2c_write和i2c_read函数。
void i2c_write(u8 add ,u8 reg ,u8 data)
{
//写 参数是设备地址和寄存器地址,以及要存的数据。
I2CStart();
I2CSendByte(add);
I2CWaitAck();
I2CSendByte(reg);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
}
uint8_t i2c_read(u8 add ,u8 reg)
{
//读取,参数是设备地址和寄存器地址
u8 data ;
I2CStart();
I2CSendByte(add);
I2CWaitAck();
I2CSendByte(reg);
I2CWaitAck();
I2CStart();
I2CSendByte(add+1);
I2CWaitAck();
data =I2CReceiveByte();
I2CWaitAck();
I2CStop();
return data;
}
这两个函数使用之后,尽量延时5ms,不然会发现蜜汁bug。
下面来个例子,将ab的值保存下来,并在启动的时候赋值给flag,先来个定义。
uint8_t flag=0;
uint8_t ab;
//然后写一个IIC的子程序:每过1s把ab的值+1,并存到eeprom中。
void I2C_Proc()
{
if(uwTick - uwtickCnt_Speed < 1000) return;
else uwtickCnt_Speed = uwTick;
ab++;
i2c_write(0xa0,1,ab);
HAL_Delay(5); //注意这个延时!
}
//初始化,然后读取存储的值。
I2CInit();
flag = i2c_read(0xa0,1);
HAL_Delay(5);
之后我们可以写一个LCD显示程序,就可以看到现象了。