赞
踩
相关说明:
开发板:CT117E-M4(STM32G431RBT6)
开发环境: CubeMX+Keil5
涉及题目:第十三届蓝桥杯嵌入式省赛第一场真题
CubeMX配置、主要函数代码及说明:
1.使能外部高速时钟:
2.配置时钟树:
3.GPIO:
4.TIM2(通道2 PA1输出方波、脉冲信号):
5.UART:
6.NVIC优先级配置
unsigned char psd[3]={0x40,0x40,0x40};//定义输入密码数组 并初始化为@@@
unsigned char psd_now[3]={0x31,0x32,0x33};//定义正确密码数组 并初始化为1,2,3的ASCII码值
unsigned char jiemian;//显示界面 0为输入密码界面 1为状态输入界面
unsigned char uled;//LED显示参数
unsigned char flag;//报警灯标志位 0为LED2熄灭 1为LED2闪烁
unsigned char error_num;//存储错误输入密码次数
unsigned char rx,rx_buf[7],dex;//串口相关变量
unsigned char pwm;//初始为0 默认输出方波 1为输出脉冲
__IO uint32_t PWM_Tick;//计时脉冲输出时间
__IO uint32_t LED_Tick;//计时LED显示时间
void Key_Proc();
void Lcd_Proc();
void Uart_Proc();
void Led_Proc();
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);
__HAL_TIM_SET_AUTORELOAD(&htim2,999);
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,500);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
HAL_UART_Receive_IT(&huart1,&rx,1);
/* 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 */
}
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==0)//密码输入界面时有效
{
if(++psd[0]>=0x3A)//初始为@时(0x40>0x3A) 按下B1变为0的ASCII值
psd[0]=0x30;//限定为0~9循环
}
break;
case 2:
if(jiemian==0)//密码输入界面时有效
{
if(++psd[1]>=0x3A)//初始为@时(0x40>0x3A) 按下B2变为0的ASCII值
psd[1]=0x30;//限定为0~9循环
}
break;
case 3:
if(jiemian==0)//密码输入界面时有效
{
if(++psd[2]>=0x3A)//初始为@时(0x40>0x3A) 按下B3变为0的ASCII值
psd[2]=0x30;//限定为0~9循环
}
break;
case 4://密码确认键
if((psd[0]==psd_now[0])&&(psd[1]==psd_now[1])&&(psd[2]==psd_now[2]))//密码输入正确
{
jiemian=1;//进入状态输出界面
uled|=0x01;//指示灯LED1点亮
LED_Tick=uwTick;//LED显示计时开始
pwm=1;//输出脉冲
PWM_Tick=uwTick;//输出脉冲计时开始
error_num=0;//错误次数清零
LCD_Clear(Black);//切换屏幕时清屏
}
else//密码输入错误 停留在密码输入界面
{
if(++error_num>=3)//错误次数+1 大于等于3时
{
LED_Tick=uwTick;//开始报警计时
flag=1;//报警灯标志位置1
}
psd[0]=psd[1]=psd[2]=0x40;//三位密码值重置为@
}
break;
}
}
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)//密码输入界面时 输出方波
{
__HAL_TIM_SET_AUTORELOAD(&htim2,999);//设置频率1000Hz
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,500);//设置占空比50%
}
else//状态输出界面时 输出脉冲
{
__HAL_TIM_SET_AUTORELOAD(&htim2,499);//设置频率2000Hz
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,50);//设置占空比10%
}
if(jiemian)//处于状态输出界面
{
if(uwTick-PWM_Tick>5000)//脉冲输出时间达到5秒
{
pwm=0;//输出5秒后转换为方波
jiemian=0;//进入密码输入界面
psd[0]=psd[1]=psd[2]=0x40;//三位密码值重置为@
LCD_Clear(Black);//切换屏幕时清屏
}
}
if(jiemian==0)//密码输入界面时
{
sprintf((char*)lcd_string," PSD");
LCD_DisplayStringLine(Line1,lcd_string);
sprintf((char*)lcd_string," B1:%c",psd[0]);//密码第一位按字符输出
LCD_DisplayStringLine(Line3,lcd_string);
sprintf((char*)lcd_string," B2:%c",psd[1]);//密码第二位按字符输出
LCD_DisplayStringLine(Line4,lcd_string);
sprintf((char*)lcd_string," B3:%c",psd[2]);//密码第三位按字符输出
LCD_DisplayStringLine(Line5,lcd_string);
}
else//状态输出界面时
{
sprintf((char*)lcd_string," STA");
LCD_DisplayStringLine(Line1,lcd_string);
if(pwm==0)//输出方波时
{
sprintf((char*)lcd_string," F:1000Hz");
LCD_DisplayStringLine(Line3,lcd_string);
sprintf((char*)lcd_string," D:50%%");
LCD_DisplayStringLine(Line4,lcd_string);
}
else//输出脉冲时
{
sprintf((char*)lcd_string," F:2000Hz");
LCD_DisplayStringLine(Line3,lcd_string);
sprintf((char*)lcd_string," D:10%%");
LCD_DisplayStringLine(Line4,lcd_string);
}
}
}
unsigned char isRxCplt()//接收数据合法时返回值为1
{
unsigned char i;
if(dex==0)//未接收到数据
return 0;
if(dex!=7)//接收数据不为7个ASCII时不合法
return 2;
if(rx_buf[3]==0x2D)//接收数据第四个为'-'时
{
for(i=0;i<3;i++)
{
if((rx_buf[i]<'0')||(rx_buf[i]>'9'))//接收数据不为阿拉伯数字时不合法
return 2;
}
for(i=4;i<7;i++)
{
if((rx_buf[i]<'0')||(rx_buf[i]>'9'))//接收数据不为阿拉伯数字时不合法
return 2;
}
return 1;
}
else//接收数据第四个不为'-'时不合法
return 2;
}
void Uart_Proc()
{
static __IO uint32_t Uart_Tick;//减速变量
unsigned char tx[21];
if(uwTick-Uart_Tick<100)
return;
Uart_Tick=uwTick;
if(isRxCplt()==1)//接收数据合法
{
if((rx_buf[0]==psd_now[0])&&(rx_buf[1]==psd_now[1])&&(rx_buf[2]==psd_now[2]))//当前密码正确
{
psd_now[0]=rx_buf[4];//修改密码
psd_now[1]=rx_buf[5];//修改密码
psd_now[2]=rx_buf[6];//修改密码
sprintf((char*)tx,"Ok\n");
HAL_UART_Transmit(&huart1,tx,strlen(tx),50);//向上位机发送OK表示修改成功
}
else//当前密码不正确
{
sprintf((char*)tx,"Error\n");
HAL_UART_Transmit(&huart1,tx,strlen(tx),50);//向上位机发送Error表示修改失败
}
}
else if(isRxCplt()==2)//接收数据不合法
{
sprintf((char*)tx,"Error\n");
HAL_UART_Transmit(&huart1,tx,strlen(tx),50);//向上位机发送Error表示修改失败
}
dex=0;//清除串口接收数组索引
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rx_buf[dex++]=rx;//一位一位存入缓存数组 索引+1
HAL_UART_Receive_IT(&huart1,&rx,1);//重新开启接收中断
}
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、LED2显示时间达到5秒
{
uled&=~0x01;//指示灯LED1熄灭
uled&=~0x02;//报警灯LED2熄灭
flag=0;//报警灯标志位清零,LED2停止闪烁
}
if(flag)//报警灯标志位为1
uled^=0x02;//LED2以0.1秒间隔闪烁
Led_Disp(uled);//LED显示函数
}
本次比赛一波三折,赛前我去赛点测试,赛点CubeMx软件不支持64位,也没有32位java环境,也没有CubeMx G4安装包,Keil软件编译有问题,我刚好我的U盘里有安装包,解决了这些问题。
比赛当天问题又出现了,我的电脑识别不了板子驱动,我检查驱动和更换电脑花费了1个半多小时,但是新电脑的Keil用调试器下载不进去,我就卸载了Keil进行重装,并安装Pack包和破解Keil,由于电脑有点卡,安装时间挺长的,安好已经两个多小时过去了,我代码只写好了底层的LED和按键,我心态挺好的,用了40分钟将程序写完,10分钟做完了选择题。
当距离考试结束还有10分钟的时候我发现我的hex文件命名错误,我命名的是12345678.hex,官方要求G12345678.hex,否则零分,我赶紧把命名修改重新生成代码并提交。
虽然有惊无险,但还是挺考验人心态的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。