零、环境配置
keil代码补全
keil pack包
cubemx配置安装包
一、LED
cubemx配置PD2引脚为输出模式
cpp
uint16_t led_value = 0x00;
void led_set(uint8_t led_dis)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,led_dis<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void led_single_on(uint8_t turn)
{
led_value = led_value | (0x01<<(turn - 1));
led_set(led_value);
}
void led_single_off(uint8_t turn)
{
led_value = led_value & (~(0x01<<(turn - 1)));
led_set(led_value);
}
void led_single_on(uint8_t turn);
void led_single_off(uint8_t turn);
通过位运算实现单独的led操作而不影响其他led灯的正常显示,便于实现led的同时闪烁和分别控制,成功解决和led灯冲突的问题
二、EPPEROM(I2C)
初始化
初始化函数【无需在cubemx配置引脚】,在while(1)前面初始化配置一下🆗,下面这个函数在提供的I2C函数里有
cpp
void I2CInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_6;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
}
EEPROM--AT24C02 只有对写操作有时间间隔要求,对读操作没有间隔要求
由上图可以得知,AT24C02读时间间隔为5ms
cpp
HAL_Delay(5); //延时5ms--AT24C02写时序要求
根据芯片手册时序图编写读写函数
cpp
//字节写函数
void at24c02_Byte_Write(unsigned char addr,unsigned char cSendByte)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(cSendByte);
I2CWaitAck();
I2CStop();
}
cpp
//随机读
unsigned char at24c02_Byte_read(unsigned char addr)
{
unsigned char dat;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
dat = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return dat;
}
三、LCD
1.LCD基本显示问题
cpp
#include "stdio.h" //进入sprintf函数的头文件
sprintf () 可以将格式化输出发送到一个字符串中
使用示例:
cpp
sprintf(text," Liquid Level ");
LCD_DisplayStringLine(Line1,(u8*)text);
2.高亮某一行
cpp
if(set_sel == Sel_3){
LCD_SetBackColor(Yellow);
}
sprintf(text," Threshold_3: %2dcm ",Threshold_3);
LCD_DisplayStringLine(Line7,(u8*)text);
LCD_SetBackColor(Black);
设置set_sel用于选择高亮的某一行
在显示前设置高亮背景颜色
在显示后设置回默认的背景颜色
3.高亮某个字符
cpp
void highlight(uint8_t *str,uint8_t pos)
{
int i = 0;
for(i = 0; i <= 20; i++)
{
if(i != pos && i!= (pos+1))
LCD_DisplayChar(Line3,(320 - (16 * i)),str[i]);
}
LCD_SetBackColor(Yellow);
LCD_DisplayChar(Line3,(320 - (16 * pos)),str[pos]);
LCD_SetBackColor(Yellow);
LCD_DisplayChar(Line3,(320 - (16 * (pos+1))),str[pos+1]);
LCD_SetBackColor(Black);
}
使用示例:
四、串口
1.串口重定向
cpp
#include "stdio.h"
cpp
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(unsigned char*)&ch,1,50);
return ch;
}
2.串口中断
3.串口DMA
4.不定长数据接收
5.指令解析
6.sscanf的使用
五、TIM
1.PWM输出(多通道脉冲输出/信号发生器)
cpp
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); //PA6--PWM输出
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1); //PA7--PWM输出
2.PWM占空比
①初始化配置
②修改比较值
cpp
__HAL_TIM_SetCompare( );
3.PWM频率设置
cpp
__HAL_TIM_SET_PRESCALER(&htim2,80-1);
4.输入捕获,双通道测量频率和占空比
cpp
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
cpp
uint16_t cnt_rising=0, cnt_falling=0;
uint16_t freq=0;
float IC_duty;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim -> Instance == TIM3)
{
if(htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
cnt_rising = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)+1;
freq = (80000000/80) / cnt_rising;
IC_duty = ((float)cnt_falling/cnt_rising)*100;
}
if(htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
cnt_falling = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)+1;
}
}
}
5.RTC时钟
6.定时器实现闪烁/步进
六、按键
短按
长按+短按
按键处理函数
七、ADC(电位器)
ADC校准
cpp
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED); //ADC校准
ADC读取值
勾选ADC2 IN15 Single-ended,其他选项默认
cpp
HAL_ADC_Start(&hadc2);
cpp
HAL_ADC_GetValue(&hadc2);
cpp
double getADCvalue(void)
{
HAL_ADC_Start(&hadc2);
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED); //ADC校准
uint32_t value = HAL_ADC_GetValue(&hadc2);
ADC_get_flag = 0;
return (value*3.3)/4095.0;
}
4095------>分辨率12bit
过采样(G4系列)
Oversampling Right Shift和Oversampling Ratio设置为对应的。
cpp
double getADCvalue(void)
{
HAL_ADC_Start(&hadc2);
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED); //ADC校准
uint32_t value = HAL_ADC_GetValue(&hadc2);
ADC_get_flag = 0;
return (value*3.3)/4095.0;
}
硬件滤波
软件滤波(一阶互补滤波)
cpp
double first_filter(double new_val,double old_val,float rate)
{
return (new_val*rate + old_val*(1-rate));
}
八、考试调试
①printf
②LCD