前言
相关说明:
开发板:CT117E-M4(STM32G431RBT6)
开发环境: CubeMX+Keil5
涉及题目:第十三届蓝桥杯嵌入式省赛第二场真题
CubeMX配置、主要函数代码及说明:
一、CubeMX配置(第十三届省赛第二场真题)
1.使能外部高速时钟:
2.配置时钟树:
3.GPIO:
4.TIM2(通道2 PA1输出脉冲信号):
5.UART:
6.NVIC优先级配置文章来源:https://www.toymoban.com/news/detail-406844.html
二、代码相关定义、声明
1.变量声明
unsigned char x[3]={0,10,10};//定义商品X数组 并分别对应初始化为购买数量、10倍单价、库存数量
unsigned char y[3]={0,10,10};//定义商品Y数组 并分别对应初始化为购买数量、10倍单价、库存数量
unsigned char jiemian;//显示界面 0为商品购买界面 1为商品价格界面 2为库存信息界面
unsigned char uled;//LED显示参数
unsigned char tx[21],rx,rx_buf[7],dex;//串口相关变量
unsigned char pwm;//初始为0 默认输出占空比5%脉冲 1为输出占空比30%的脉冲
unsigned char e2prom[7];//将从E2PROM中读出的数据暂存此数组中
__IO uint32_t PWM_Tick;//计时脉冲输出时间
__IO uint32_t LED_Tick;//计时LED显示时间
2.函数声明
void Key_Proc();
void Lcd_Proc();
void Uart_Proc();
void Led_Proc();
三、主要函数
1.main函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
I2CInit();
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
HAL_UART_Receive_IT(&huart1,&rx,1);
IIC_Read(e2prom,0,7);//读出E2PROM存储的商品信息和是否第一次运行标志位
HAL_Delay(100);
if((e2prom[4]==0x77)&&(e2prom[5]==0x7A)&&(e2prom[6]==0x64))//STM32不是第一次运行
{
x[2]=e2prom[0];//商品信息数据交换
y[2]=e2prom[1];
x[1]=e2prom[2];
y[1]=e2prom[3];
}
else//STM32第一次运行
{
e2prom[4]=0x77;e2prom[5]=0x7A;e2prom[6]=0x64;//博主自定义的信息 表示STM正在运行第一次
e2prom[0]=x[2];e2prom[1]=y[2];e2prom[2]=x[1];e2prom[3]=y[1];//将初始的商品库存和价格按规定的位置写入E2PROM
IIC_Write(e2prom,0,7);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
Key_Proc();
Lcd_Proc();
Uart_Proc();
Led_Proc();
}
/* USER CODE END 3 */
}
2.按键扫描、E2PROM存储、打印购买信息
void Key_Proc()
{
static __IO uint32_t Key_Tick;//减速变量
static unsigned char key_old;
unsigned char key_down,key_value;
if(uwTick-Key_Tick<50)
return;
Key_Tick=uwTick;
key_value=Key_Scan();
key_down=key_value&(key_value^key_old);
key_old=key_value;
switch(key_down)
{
case 1:
if(++jiemian>2)//界面切换
jiemian=0;
LCD_Clear(Black);//切换屏幕时清屏
break;
case 2://商品x
if(jiemian==0)//商品购买界面
{
if(++x[0]>x[2])
x[0]=0;
}
else if(jiemian==1)//商品价格界面
{
if(++x[1]>20)
x[1]=10;
IIC_Write(&x[1],2,1);//写入E2PROM商品x单价
}
else//商品库存界面
{
x[2]++;
IIC_Write(&x[2],0,1);//写入E2PROM商品x库存数量
}
break;
case 3://商品y
if(jiemian==0)//商品购买界面
{
if(++y[0]>y[2])
y[0]=0;
}
else if(jiemian==1)//商品价格界面
{
if(++y[1]>20)
y[1]=10;
IIC_Write(&y[1],3,1);//写入E2PROM商品y单价
}
else//商品库存界面
{
y[2]++;
IIC_Write(&y[2],1,1);//写入E2PROM商品y库存数量
}
break;
case 4://商品确认键
if(jiemian==0)//商品购买界面
{
x[2]=x[2]-x[0];//商品x库存减少
y[2]=y[2]-y[0];//商品y库存减少
if(x[0]!=0)//商品X购买数量不为0 库存发生变化
IIC_Write(&x[2],0,1);//写入E2PROM商品x库存数量
sprintf((char*)tx,"X:%d,Y:%d,Z:%0.1f\n",x[0],y[0],0.1*x[0]*x[1]+0.1*y[0]*y[1]);//打印总价、发送购买信息
HAL_UART_Transmit(&huart1,tx,strlen(tx),50);
uled|=0x01;//指示灯LED1点亮
LED_Tick=uwTick;//LED显示计时开始
pwm=1;//输出2kHz 占空比30%脉冲
PWM_Tick=uwTick;//输出脉冲计时开始
if(y[0]!=0)//商品Y购买数量不为0 库存发生变化
IIC_Write(&y[2],1,1);//写入E2PROM商品y库存数量
x[0]=y[0]=0;//商品购买数量重置为0
}
break;
}
}
3.屏幕显示、PWM输出
void Lcd_Proc()
{
static __IO uint32_t Lcd_Tick;//减速变量
unsigned char lcd_string[21];
if(uwTick-Lcd_Tick<100)
return;
Lcd_Tick=uwTick;
if(pwm==0)//输出2kHz 占空比5%脉冲
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,25);
else//输出2kHz 占空比30%脉冲
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,150);
if(uwTick-PWM_Tick>5000)//脉冲输出时间达到5秒
pwm=0;//输出5秒后转换为占空比5%的脉冲
if(jiemian==0)//商品购买界面时
{
sprintf((char*)lcd_string," SHOP");
LCD_DisplayStringLine(Line1,lcd_string);
sprintf((char*)lcd_string," X:%d",x[0]);//显示商品X的购买数量
LCD_DisplayStringLine(Line3,lcd_string);
sprintf((char*)lcd_string," Y:%d",y[0]);//显示商品Y的购买数量
LCD_DisplayStringLine(Line4,lcd_string);
}
else if(jiemian==1)//商品价格界面时
{
sprintf((char*)lcd_string," PRICE");
LCD_DisplayStringLine(Line1,lcd_string);
sprintf((char*)lcd_string," X:%3.1f",0.1*x[1]);
LCD_DisplayStringLine(Line3,lcd_string);
sprintf((char*)lcd_string," Y:%3.1f",0.1*y[1]);
LCD_DisplayStringLine(Line4,lcd_string);
}
else
{
sprintf((char*)lcd_string," REP");
LCD_DisplayStringLine(Line1,lcd_string);
sprintf((char*)lcd_string," X:%d ",x[2]);
LCD_DisplayStringLine(Line3,lcd_string);
sprintf((char*)lcd_string," Y:%d ",y[2]);
LCD_DisplayStringLine(Line4,lcd_string);
}
}
4.判断串口接收数据是否合法
unsigned char isRxCplt()//接收数据合法时返回值为1
{
unsigned char i;
if(dex==0)//未接收到数据
return 0;
if(dex!=1)//接收数据不为1个ASCII时不合法
return 2;
if(rx_buf[0]==0x3F)//接收数据为'?'时
return 1;
else//接收数据不为'?'时不合法
return 2;
}
5.查询当前商品价格
void Uart_Proc()
{
static __IO uint32_t Uart_Tick;//减速变量
if(uwTick-Uart_Tick<100)
return;
Uart_Tick=uwTick;
if(isRxCplt()==1)//接收数据合法
{
sprintf((char*)tx,"X:%3.1f,Y:%3.1f\n",0.1*x[1],0.1*y[1]);
HAL_UART_Transmit(&huart1,tx,strlen(tx),50);//向上位机发送OK表示修改成功
}
else if(isRxCplt()==2)//接收数据不合法
{
sprintf((char*)tx,"Query format error\n");
HAL_UART_Transmit(&huart1,tx,strlen(tx),50);//向上位机发送Error表示修改失败
}
dex=0;//清除串口接收数组索引
}
6.串口中断
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rx_buf[dex++]=rx;//一位一位存入缓存数组 索引+1
HAL_UART_Receive_IT(&huart1,&rx,1);//重新开启接收中断
}
7.LED指示功能
void Led_Proc()
{
static __IO uint32_t Led_Tick;//减速变量
if(uwTick-Led_Tick<100)//0.1秒间隔闪烁
return;
Led_Tick=uwTick;
if(uwTick-LED_Tick>=5000)//LED1点亮时间达到5秒
uled&=~0x01;//指示灯LED1熄灭
if((x[2]==0)&&(y[2])==0)//商品x和商品y库存均为0
uled^=0x02;//LED2以0.1秒间隔闪烁
else
uled&=~0x02;//指示灯LED2熄灭
Led_Disp(uled);
}
四、编程感受、细节剖析、赛前预测
博主参加的是第一场,第二场结束后由于学校统一做核酸,未能及时发布,第一时间收到真题后,便打开了电脑STM32CubeMx软件配置,第二场的题和第一场的很像,万变不离其宗,博主也是很快就写好了代码。
第二场的串口很简单,只是接收一个字符和发送一个字符串,很常规,难点在于连续改价格和库存时E2PROM的连续读写,但放入按键扫面里面就可以很好的解决这个问题,而且题目要求库存发生变化时才写入E2PROM,所以当购买数量为0时,按下B4键不应进行E2PROM的写入,同时单片机第一次上电的时候需要满足题意的价格1.0,库存10,之后重新上电应保证掉电保存,所以需要判断一下你的单片机是否第一次上电,再者需要注意的是两个库存均为0时LED2才开始以0.1秒间隔闪烁。细节很多,但各个模块都很常规,不难,相信各位大佬都能游刃有余。
赛前一晚有学弟问我串口相关方面的知识,然后给他预测了一下会考察的模块,今天应征了我的预测,还挺开心的。
在这里提前预祝各位大佬都能拿下省一,共同进击国赛!文章来源地址https://www.toymoban.com/news/detail-406844.html
五、链接
1.第十三届蓝桥杯嵌入式省赛第二场真题PDF
2.第十三届蓝桥杯嵌入式国赛真题(基于HAL库的巨简代码+超级详解)
3.第十三届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)
4.第十二届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)
到了这里,关于第十三届蓝桥杯嵌入式省赛第二场真题(基于HAL库的巨简代码+超级详解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!