当前位置: 首页 > article >正文

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

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为低电平 -> 更新文件

->

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,复制以下代码

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 -> 使能中断 -> 更新文件

->

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;

    }

}

->

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//中断回调函数(中断服务函数)

{

    static uint8_t Count0;

    if(htim -> Instance == TIM6)

    {

        if(++Count0 >= 20)
    
        {

            Count0 = 0;

            KeyStart = 1;

        }

    }

}

->

HAL_TIM_Base_Start_IT(&htim6);//使能定时器中断

Key(长按键)

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:占空比初值 -> 更新文件

->

HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);//使能PWM某通道输出

->

__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头文件 ->

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;
}

->

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文件 ->

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);
}

->

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);//使能输入捕获中断

ADC + DMA

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

HAL_ADC_Start_DMA(&hadc1,(uint32_t *)adc1,1); 
HAL_ADC_Start_DMA(&hadc2,(uint32_t *)adc2,1); //使能DAM转运

IIC

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

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->

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);
		}
	}
}

->

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

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

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

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

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

5 资料

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


http://www.kler.cn/news/295203.html

相关文章:

  • BAT脚本实现基础爬虫功能
  • 上海亚商投顾:深成指、创业板指均涨超1%,华为产业链反复活跃
  • 深入解析 Node.js:基础知识、环境搭建与核心模块详解
  • 文法—语法推导树例题
  • 面对Redis数据量庞大时的应对策略
  • 物联网之流水LED灯、正常流水灯、反复流水灯、移动流水灯
  • SprinBoot+Vue餐饮连锁店管理系统的设计与实现
  • 网络编程day03(网络体系结构、调试命令、TCP/IP对比)
  • el-table 单元格,双击编辑
  • some electronic products
  • isxdigit函数讲解 <ctype.h>头文件函数
  • Sysbench性能测试工具的安装与使用
  • Kettle使用命令pan/kitchen执行任务时传参问题
  • Node.js学习记录(一)
  • MySQL中常见的存储引擎有什么?
  • python操作数据对象方法和高阶函数
  • 19章 泛型(编程练习题)
  • windows C++-并行编程-将使用缩减变量的 OpenMP 循环转换为使用并发运行时
  • 经验笔记:负载均衡
  • Hive的优势与使用场景
  • WebTopo 组态软件+ARM 工业计算机:重塑污水处理
  • macos系统内置php文件列表 系统自带php卸载方法
  • 周报2024、9、8
  • 消息认证码(MAC)
  • HTTP与HTTPS:网络通信的安全之旅
  • 通信工程学习:什么是AB地址总线、DB数据总线、CD控制总线
  • 今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 9月8日,星期日
  • [动态规划] 删除并获得点数
  • el-table 封装表格(完整代码-实时更新)
  • 【技术调研】三维(0)-webGL、三维基础知识、前置知识、数学知识以及简单示例