蓝桥杯嵌入式
蓝桥杯嵌入式
考点
时钟RCC__HSEz
输入24MHz的HSE通过PLL锁相环输出80MHz
LED:LD1~8 ---PC8~15,低电平电亮
锁存器LE:PD2,=1选通,=0锁存
先将锁存器LE引脚初始化为低电平,锁存LED状态,需要操作LED时再开启,操作完即关闭,避免LED与LCD的互相影响
key:
从上到小,按键B1~4,
PB0~2,PA0,上拉,检测低电平
移植LCD:
不需要再CubeMX中进行引脚配置
将下类文件添加进工程文件夹
main中只用声明lcd.h头文件就可以使用LCD
串口通信
UART1(9600)
PA9,10(需手动配置,默认为PC端口)
异步模式:
开启串口中断
添加的头文件
>stdio.h
(标准输入输出头文件)
stdio.h
头文件中包含了以下几类函数:
- 输入输出函数:
printf
:格式化输出函数,用于将数据输出到标准输出(通常是屏幕)。scanf
:格式化输入函数,用于从标准输入(通常是键盘)读取数据。fopen
:打开文件。fclose
:关闭文件。fread
:从文件中读取数据。fwrite
:向文件中写入数据。fgets
:从文件中读取一行数据。fputs
:向文件中写入一行数据。
- 文件操作函数:
remove
:删除文件。rename
:重命名文件。tmpfile
:创建临时文件。tmpnam
:生成临时文件名。
- 控制函数:
setbuf
:设置缓冲区。setvbuf
:设置缓冲区。getchar
:从标准输入读取一个字符。putchar
:向标准输出写入一个字符。
>string.h
(字符串处理头文件)
string.h
头文件中包含了以下几类函数:
- 字符串操作函数:
strlen
:计算字符串的长度。strcpy
:复制字符串。strncpy
:复制字符串的一部分。strcat
:连接两个字符串。strncat
:连接两个字符串的一部分。strcmp
:比较两个字符串。strncmp
:比较两个字符串的一部分。strchr
:查找字符串中首次出现的字符。strrchr
:查找字符串中最后一次出现的字符。strstr
:查找子字符串。strtok
:分割字符串。
- 内存操作函数:
memcpy
:复制内存块。memmove
:移动内存块。memcmp
:比较内存块。memset
:设置内存块。
- 字符操作函数:
isalpha
:检查字符是否为字母。isdigit
:检查字符是否为数字。islower
:检查字符是否为小写字母。isupper
:检查字符是否为大写字母。isspace
:检查字符是否为空白字符。toupper
:将字符转换为大写。tolower
:将字符转换为小写。
声明串口句柄
UART_HandleTypeDef huart1;
因为CubeMX中自动生成了串口初始化,并包含在MX_GPIO_Init()中,故不用再次初始化
设置串口
串口发送
sprintf(str, "%04d:Hello,world.\r\n", counter);//**格式化字符串**
HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50);//**通过UART发送字符串**
串口接收
main():
HAL_UART_Receive_IT(&huart1, rx, 1);//启动接收中断。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//串口接收回调函数(弱函数) { GPIOC->ODR = ((rx[0] << 8) | 0x00FF);//将接收到的二进制数据写入C端口,控制LED HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);//1选通锁存器 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //0 锁存 HAL_UART_Receive_IT(&huart1, rx, 1); }
ADC测量

PB15__J11 电压采集1 ADC2_IN15
PB12__J12 电压采集2 ADC1_IN11

不用设置NVIC
获取ADC数值函数:
uint16_t getADC2_PB15_VL1(void)//PB15--ADC2_IN15
{
uint16_t adc = 0;
HAL_ADC_Start(&hadc2);//开启ADC2
adc = HAL_ADC_GetValue(&hadc2);//获取adc数值
return adc;
}
uint16_t getADC1_PB12_VL2(void)//PB12--ADC1_IN11
{
uint16_t adc = 0;
HAL_ADC_Start(&hadc1);
adc = HAL_ADC_GetValue(&hadc1);
return adc;
}
显示电压函数:
unsigned char buf[20];//存储电压值
sprintf(buf, " VAL:%.2fV", getADC2_PB15_VL1()*3.3/4096);//转化成电压值,保存在char型变量buf【20】中
LCD_DisplayStringLine(Line8, (uint8_t *)buf);//将cahr型变量转化成unsigned char 型变量,并在lcd中显示
sprintf(buf, " VAL:%.2fV", getADC1_PB12_VL2()*3.3/4096); LCD_DisplayStringLine(Line9, (uint8_t *)buf);
解决LCD与LED引脚冲突
先将锁存器LE引脚初始化为低电平,锁存LED状态,需要操作LED时再开启,操作完即关闭,避免LED与LCD的互相影响
TIME1定时1s
选择定时器时钟输入源:
Internal Clock:内部时钟
NVIC开启定时器1更新中断
定时周期1s,(8000PSCX1000ARR)/8*10^6=0.1s
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器回调函数(中断服务函数)处理定时器周期溢出事件
{
t++;//定时溢出时执行程序
}
main(){
HAL_TIM_Base_Start_IT(&htim1);//开启定时器中断
......
}
while(1)中
sprintf(buf, " t=%d", t);//,保存在char型变量buf【20】中
LCD_DisplayStringLine(Line8, (uint8_t *)buf);//将cahr型变量转化成unsigned char 型变量,并在lcd中显示
基础定时器TIM6
activate:激活
pluse:脉冲

系统时钟80MHz

定时周期T=(8000X1000)/8X10^6=0.1s
PSC:8000-1,ARR=1000-1
自动重装预寄存器:auto-reload preload,无影响

开启更新中断
频率测量,(定时器输入捕获,当计数器)
R39__PB4 TIM3_CH1,TIM16_CH1
R40__PA15 TIM2_CH1,TIM8_CH1
配置定时器为输入捕获模式
配置PSC为80-1,重装值为0xFFFF(65536)

开启定时器中断
f(捕获)=1MHz(分频后)/计数值
定时器回调函数:
uint32_t cc1_value_1,cc1_value_2 = 0; uint32_t f39,f40 = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//定时器回调函数
{
if(htim->Instance ==TIM3)//判断是否是定时器3触发的中断
{
cc1_value_1 = __HAL_TIM_GET_COUNTER(&htim3);//获取计数值
__HAL_TIM_SetCounter(&htim3,0);//清除计数值
f39 = 1000000/cc1_value_1;//计算频率
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);//重新启动定时器的输入捕获功能,并使能相应的中断。
}
if(htim->Instance ==TIM2)
{
cc1_value_2 = __HAL_TIM_GET_COUNTER(&htim2);
__HAL_TIM_SetCounter(&htim2,0);
f40 = 1000000/cc1_value_2;
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
}
}
相关初始化
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);//启动定时器的输入捕获功能,并使能相应的中断。
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
读取频率
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
sprintf(buf, " FRQ(R39):%dHz ",f39);
LCD_DisplayStringLine(Line8, (uint8_t *)buf);
HAL_Delay(200);
sprintf(buf, " FRQ(R40):%dHz ",f40);
LCD_DisplayStringLine(Line9, (uint8_t *)buf);
HAL_Delay(200);
}
PWM输出(占空比调节)
PA2__TIM2_CH2
选择定时器2通道2功能为
设置为1Khz频率
PSC:800
ARR:100
f输出=80MHz/(PSC*ARR)=80x10^6/(800x100)=1000hz

开启输出比较
不用设置定时器中断(不开启)
初始化PWM输出
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);//开启time2,通道2pwm输出
TIM2->CCR2 =50;
uint16_t pwmduty=50;//占空比
占空比=输出比较寄存器值/自动重装载值,pwmduty=CCR/ARR=CCR2/100,即在ARR=100时,CCR的值即为占空比(<=100)
更改占空比(自己定义)
TIM2->CCR2 =pwmduty;
pwmduty++;
HAL_Delay(10);
if(pwmduty>95)pwmduty=0;
EEPROM(移植库文件,无需CubeMX配置)

A2=A1=A0=0
地址0xa0写
0xa1读
将下面文件拷贝进工程
引用头文件
在i2c_hal.c文件中编写iic读取EEPROM和写入函数
写入函数(器件内地址,要写入的数据)
void eeprom_write(uint8_t addr, uint8_t dat)
{
I2CStart();
I2CSendByte(0xa0);//器件地址
I2CWaitAck();//等待应答
I2CSendByte(addr);//期间内要操作的地址0~255???
I2CWaitAck();
I2CSendByte(dat);//写入的数据
I2CWaitAck();
I2CStop();
HAL_Delay(20);
}
读取函数(器件内地址)
uint8_t eeprom_read(uint8_t addr)
{
I2CStart();
I2CSendByte(0xa0);//器件地址
I2CWaitAck();//等待应答
I2CSendByte(addr);//期间内要操作的地址0~255???
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);//读取命令
I2CWaitAck();
uint8_t dat = I2CReceiveByte();//接收数据
I2CSendNotAck(); //主机不应答 从机不再发数据
I2CStop();
return dat;
}
初始化,写入,读取
I2CInit();
eeprom_write(0, 15);//在0地址写入15
uint8_t dat = eeprom_read(0);//读取0地址
char text[20];
显示到Lcd
sprintf(text, " %d ", dat);//将数据dat转化成字符串保存在text数组变量中
LCD_DisplayStringLine(Line0, (uint8_t *)text);
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库