蓝桥杯嵌入式国三备赛经验分享

1 学习STM32入门视频

向大家推荐一套宝藏级别的视频:
【STM32入门教程-2023版 细致讲解 中文字幕】

如果已经比过蓝桥杯单片机或学习过单片机相关课程的同学,你们可以尝试不需要STM32套件进行学习。如果没有学过单片机相关课程的同学,可以买套件边用边学。

尽量把这套视频看完,无论是对参加蓝桥杯嵌入式设计与开发竞赛(蓝桥杯)、嵌入式芯片与系统设计大赛STM32赛道(嵌入式大赛)或全国大学生物联网设计竞赛(华为杯)都有好处!

2 学习嵌入式开发板备赛视频

我主要看的是这套嵌入式视频:

【【备战2024蓝桥杯 嵌入式组】CT117E-M4 新款开发板 3小时省赛模块 速成总结】

从视频中可以学习到一些好的代码编写方式,从而避免各个外设的冲突、提高硬件运行效率。

3 备赛笔记

GPIO_Mode_AIN = 0x0, //模拟输入

GPIO_Mode_IN_FLOATING = 0x04, //浮空输入

GPIO_Mode_IPD = 0x28, //下拉输入

GPIO_Mode_IPU = 0x48, //上拉输入

GPIO_Mode_Out_OD = 0x14, //开漏输出

GPIO_Mode_Out_PP = 0x10, //推挽输出

GPIO_Mode_AF_OD = 0x1C, //复用开漏

GPIO_Mode_AF_PP = 0x18 //复用推挽

GPIO_SetBits //设置成高电平

GPIO_ResetBits //设置成低电平

HAL_GPIO_Write();//写GPIO电平状态函数

Key_State 里面的Key一定要初始化Key = 0;

长按键需要给25延时(Key_Time1)+长按键启用标志位

双击按键需要给40延时(Key_Time2)+双击按键启用标志位+暂时双击按键号

通用定时器可以产生4路频率相同,占空比不同的PWM输出

高级定时器可以产生7路频率相同,占空比不同的PWM输出

%d数据后面加空格 防止数据末位不清除

__HAL_TIM__SETCOMPARE(定时器,通道x, 占空比);

AT24C02 写一条语句延时5ms

MCP4017的从机地址(写操作):0X5E

随着我们向MCP中输入的数越大,他对应的电阻也就越大,当我们传入0x7f时,对应的电阻就是100K。这里要注意的一点是,我们写进去的一个数字(0-127),读出来也是一个数字,转化为电阻阻值:R = 787.4 * read_resistor 欧,电压:3.3*(R/(R+10)) (假设外接的电压为3.3)

新建工程

开启时钟(选择外部时钟) -> 配置时钟树 -> 配置DAP下载模式 -> 工程名 -> 配置MDK文件 -> 勾上生成code选项 -> 生成文件 -> 打开Keil -> 配置DAP下载 -> 勾上清除并更新 -> 建立bsp文件夹

LED

在CubeMX选择PC8-PC15、PD2为推挽输出模式 -> 配置PC8-PC15为高电平,PD2为低电平 -> 更新文件

->

cs 复制代码
void LED_Display(uchar data)
{
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC, (~data)<<8, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

(在main.c文件写代码时,写在Bagin和End注释之间)

LCD

复制资源包里LCD例程中2.h文件、1.c文件 -> 打开main.c,复制以下代码

cs 复制代码
LCD_Init();

LCD_Clear(Black);

LCD_SetBackColor(Black);

LCD_SetTextColor(White);

LCD_DisplayStringLine(Line9, (unsigned char *)str);

-> 创建char str[30];、引用"stdio.h"使用sprintf函数

Key(短按键)

在CubeMX打开TI63时钟配置外部时钟源 -> 配置PSC、ARR -> 使能中断 -> 更新文件

->

cs 复制代码
uint8_t Key_State(void)

{

    uchar Key = 0;

    if(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0))

    Key = 1;
  
    if(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1))

    Key = 2;

    if(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2))

    Key = 3;

    if(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0))
    
    Key = 4;



    return Key;

}

void Key_Loop(void)

{

    static uint8_t LastState, NowState;

    uint8_t i;

    LastState = NowState;
    
    NowState = Key_State();

    for(i = 1;i <= 4;i ++)

    {

    if(LastState == 0 && NowState == i)

    KeyNum = i;

    }

}

->

cs 复制代码
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//中断回调函数(中断服务函数)

{

    static uint8_t Count0;

    if(htim -> Instance == TIM6)

    {

        if(++Count0 >= 20)
    
        {

            Count0 = 0;

            KeyStart = 1;

        }

    }

}

->

cs 复制代码
HAL_TIM_Base_Start_IT(&htim6);//使能定时器中断

Key(长按键)

cs 复制代码
uint8_t Key_Short, Key_Long, Key_Time, Long_State = 1;

void Key_Loop(void)
{
	static uint8_t LastState, NowState;
	uint8_t i;
	LastState = NowState;
	NowState = Key_State();
	for(i = 1;i <= 4;i ++)
	{
		if(LastState == 0 && NowState == i)
		Key_Time = 0;
		if(LastState == i && NowState == i)
		{
			if(++Key_Time >= 25 && Long_State)
			{
				Key_Long = i;
				Long_State = 0;
			}
		}
		if(LastState == i && NowState == 0)
		{
			if(Key_Time < 25)
			Key_Short = i;
			Long_State = 1;
		}
	}
}

PWM

在CubeMX打开相应定时器选择PWM生成选项 -> 配置时钟PSC:待定频率,ARR:100-1、CCR:占空比初值 -> 更新文件

->

cs 复制代码
HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);//使能PWM某通道输出

->

cs 复制代码
__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, PA6_PWM);//改变占空比

IC(测频率+占空比):

在CubeMX打开相应定时器 - > 配置Clock Source -> 选择CH1为直接通道、CH2为间接通道 -> 配置时钟PSC:80-1、ARR满重装值 -> CH1为上升沿触发、CH2为下降沿触发 -> 配置从模式(Combined Reset Trigger Mode) -> 选择触发源(TI1FP1)-> 更新文件 -> 创建IC.c、IC.h文件 -> 引入tim.h头文件 ->

cs 复制代码
uint32_t Read_Fre(uint8_t Command)
{

	if(Command == 15) return 1000000 / (HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1) + 1);
	else if(Command == 4) return 1000000 / (HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1) + 1);
	else return 0;
}

double Read_Buty(uint8_t Command)
{
    if(Command == 15) return (HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2) + 1) * 100.0 / (HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1) + 1);
	else if(Command == 4) return (HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2) + 1) * 100.0 / (HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1) + 1);
	else return 0;
}

->

cs 复制代码
HAL_TIM_IC_Start(&htim2, TIM_CHANNEL_1);
HAL_TIM_IC_Start(&htim3, TIM_CHANNEL_1);//使能通道1
HAL_TIM_IC_Start(&htim2, TIM_CHANNEL_2);
HAL_TIM_IC_Start(&htim3, TIM_CHANNEL_2);//使能通道2

IC(中断测频率)

在CubeMX打开相应定时器TIMx的时钟 -> 选择相应通道CHx -> 配置时钟PSC:80-1、ARR满重装值-> 使能中断 -> 更新文件 -> 创建IC.c、IC.h文件 ->

cs 复制代码
uint32_t TIM2_IC_CRR1;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim -> Instance == TIM2)
	{
		TIM2_IC_CRR1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
		__HAL_TIM_SetCounter(htim, 0);
	}
}

uint32_t Read_Fre(void)
{
	return 1000000 / (TIM2_IC_CRR1 + 1);
}

->

cs 复制代码
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);//使能输入捕获中断

ADC + DMA

在CubeMX打开相应引脚ADC通道 -> 配置ADC1、ADC2中相应通道使能(Single-ended) -> 使能连续转换 -> 添加DAM -> 配置循环模式Circular -> 使能DMA请求为连续模式 -> 失能DMA中断 -> 更新文件 ->

cs 复制代码
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)adc1,1); 
HAL_ADC_Start_DMA(&hadc2,(uint32_t *)adc2,1); //使能DAM转运

IIC

在CubeMX设置PB6、PB7引脚为输出模式 ->

cs 复制代码
void Write_AT24C02(uint8_t Command, uint8_t Data)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(Command);
	I2CWaitAck();
	I2CSendByte(Data);
	I2CWaitAck();
	I2CStop();
}

uint8_t Read_AT24C02(uint8_t Command)
{
	uint8_t Data;
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(Command);
	I2CWaitAck();
	I2CStart();
	I2CSendByte(0xa0 | 0x01);
	I2CWaitAck();
	Data = I2CReceiveByte();
	I2CSendNotAck();//不需要继续读就给非应答
	I2CStop();
	
	return Data;
}

uint8_t Read_AT24C02(uint8_t Command)
{
	uint8_t Data;
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(Command);
	I2CWaitAck();
	I2CStart();
	I2CSendByte(0xa0 | 0x01);
	I2CWaitAck();
	Data = I2CReceiveByte();
	I2CSendNotAck();//不需要继续读就给非应答
	I2CStop();
	
	return Data;
}

USART1

在CubeMX配置USART1模式为Asynchronous -> 配置波特率 -> 使能中断 -> 配置PA9、PA10为USART1 -> 更新文件 -> 创建MyUSART.c、.h文件 -> 引用usart.h->

cs 复制代码
uint8_t Rxdata,Receive_Over, pRxPacket;
char RxPacket[30];

void Send_USART(char *data)
{
	HAL_UART_Transmit(&huart1, (uint8_t  *)data, strlen(data), 50);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart -> Instance == USART1)
	{
		HAL_UART_Receive_IT(huart, &Rxdata, 1);
		RxPacket[pRxPacket ++] = RXdata;
	}
}

void Receive_USART(void)
{
	static uint8_t p;
	if(pRxPacket != 0)
	{
		p = pRxPacket;
		HAL_Delay(1);
		if(p == pRxPacket)
		{
			Receive_Over =1;
Send_USART(RxPacket);
			pRxPacket = 0;
memset(RxPacket, 0, 30);
		}
	}
}

->

cs 复制代码
HAL_UART_Receive_IT(&huart1, &Rxdata, 1);//使能接收中断
4 备赛过程

嵌入式省赛备赛过程与单片机备赛过程类似,这里不再赘述,详情可以查看博主的另一篇博客:

【蓝桥杯单片机大一零基础到国二经验分享】

奇数届嵌入式国赛备赛时,可以多学习一些串口方面的c语言函数,比如第十五届嵌入式串口相关的收发数据及提取数据就比较多。

偶数届嵌入式国赛备赛时,需要学习扩展板相关外设的使用。

5 资料

如需十五届嵌入式资料可以私信我,本人很乐意开源,欢迎大家在评论区交流学习,预祝大家在蓝桥杯嵌入式设计与开发竞赛中取得优异成绩!!!

相关推荐
CV金科1 小时前
蓝桥杯-STM32G431RBT6(解决LCD与LED引脚冲突的问题)
c语言·stm32·单片机·嵌入式硬件·蓝桥杯
每天的积累1 小时前
STM32与ESP8266的使用
stm32·单片机·嵌入式硬件
蜡笔小新星2 小时前
切换淘宝最新镜像源npm
vue.js·经验分享·学习·npm·node.js
管家婆客服中心2 小时前
管家婆云辉煌手机端怎么连接蓝牙打印机?
经验分享·管家婆软件·管家婆软件常见问题
南斯拉夫的铁托3 小时前
线性代数(宋浩版)(4)
经验分享·笔记·线性代数
小手智联老徐3 小时前
MATLAB 从 R2024B 开始支持树莓派 5
嵌入式硬件·matlab·树莓派
烟雨金城4 小时前
invalid character ‘‘ looking for beginning of object key string
经验分享
SunriseSurfer4 小时前
华为发布大容量128TB SSD:空间利用率提升10倍
经验分享·华为
TIF星空14 小时前
【从0开始在CentOS 9中安装redis】
linux·运维·服务器·经验分享·redis·笔记·centos
Whappy00116 小时前
51单片机-DS18B20(温度传感器)&AT24C02(存储芯片) & IIC通信-实验2-温度实时监测(可设置阈值)
单片机·嵌入式硬件·51单片机