目录
GPIO配置
串口
定时器
LCD
代码
本次教程以G431新板子为例,我们基于HAL库进行编写程序,这样能大大提高效率
题目:设计计费停车场
大家可以去官网寻找题目的具体要求,保证可观性,我只截取部分截图
整套题最大的难度就是串口接收数据,保证以下题目要求:
理清楚整体逻辑,
先配置外部时钟
主要配置按键和led灯,题目中有这一类的要求比较简单,我们不做细讲
按键内部原理图
led内部原理图
HAL库配置如下
由于led灯是低电平点亮,所以我们设置为初始高电平,按键设置浮空输入
还有一点非常重要,我们一定要初始化PD2,由于在G431开发板中,lcd和led是共同用一些引脚的,这就会导致出现一些相矛盾的问题,当lcd要用的时候,就会无意中点亮led,因此内部设置了一个引脚PD2来控制开门关门,当PD2为低电平的时候关门,led和lcd不连,当PD2为高电平的时候开门,这时候我们就可以点亮led灯,总之,pD2就像一个阻隔器一样,可以阻隔LCD和LED不连通
我们选择异步时钟,9600波特率(题目要求)
我们需要用到接收中断,因此打开串口中断
我们需要输出pwm波(题目要求),设置PWM输出模式,配置成2KHZ
赛点会提供代码,将提供的代码移植到目的工程就行
key和led
void led_play(uint8_t suffe )
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|
GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, suffe<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2,GPIO_PIN_RESET);
}
suffer可以从00000000-11111111,那个位(8位从低到高分别对应,led1,led2....,led8)为1那个灯就亮
unsigned char key_check(){
uint8_t sure;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)== GPIO_PIN_RESET)
sure = 1 ;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)== GPIO_PIN_RESET)
sure = 2 ;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)== GPIO_PIN_RESET)
sure = 3 ;
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)== GPIO_PIN_RESET)
sure = 4;
return sure;
}
此函数检测那个按键按下或者刚抬上来
void key_project(){
if(uwTick-user_uwTick1<30)
return ;
else
user_uwTick1 = uwTick;
keyvule = key_check();
keyvule_down = keyvule &(keyvule^keyvule_old);
keyvule_up = ~keyvule & (keyvule^keyvule_old);
keyvule_old = keyvule;
if(keyvule_down == 1)//B1
{
screen = screen^0x01;
LCD_Clear(Black);
//led_play(0x00);
}
if(keyvule_down == 2)//B2
{
if(screen==1)
{
CNfara+=0.50f;
VNfara+=0.50f;
}
}
if(keyvule_down == 3)//B3
{
if(screen==1){
if( VNfara>0.5f)
{
CNfara-=0.5f;
VNfara-=0.5f;
}
}
}
按键控制函数,所有关于按键的控制全部写在里面了,大家可以看一下,不是太难我们就不详解了
lcd相关控制代码
void lcd_project(){
if(uwTick-user_uwTick2<100)//延时(ms)
return ;
else
user_uwTick2 = uwTick;
if(screen == 0)
{
sprintf((char *)display," Data ");
LCD_DisplayStringLine(Line1,display);
sprintf((char *)display," CNBR:%d",carCN_count);
LCD_DisplayStringLine(Line3,display);
sprintf((char *)display," VNBR:%d",carVN_count);
LCD_DisplayStringLine(Line5,display);
sprintf((char *)display," IDLE:%d",rlaxcar);
LCD_DisplayStringLine(Line7,display);
}
else if(screen == 1)
{
sprintf((char *)display," Para ");
LCD_DisplayStringLine(Line1,display);
sprintf((char *)display," CNBR:%3.2f",CNfara);
LCD_DisplayStringLine(Line3,display);
sprintf((char *)display," VNBR:%3.2f",VNfara);
LCD_DisplayStringLine(Line5,display);
}
}
tim定时器pwm输出部分
通过B4进行控制切换pwm波输出状态
uart.c相关
车库构建(我们使用结构体)
我们将通过串口发送到单片机中的数据一个一个传进来送到buffe数组里面
判断字符是否合理
uint8_t judge_char(){
uint8_t i,ax;
if(couter!=22)
return 0;
if (((buffe[0]=='V'||buffe[0]=='C')&&( buffe[1]=='N')&& (buffe[2]=='B')&&
(buffe[3] =='R')&&(buffe[4]==':')&&(buffe[9]==':') )== 1)
{
for(i=10;i<22;i++)
{
if(buffe[i]<= '9'&&buffe[i]>='0')
ax=1;
else
{
sprintf((char *)str_str, "Error\r\n");
HAL_UART_Transmit(&huart1,(unsigned char *)str_str, strlen((char *)str_str), 50);
couter=0;
ax=0;
}
}
}
else
{
ax=0;
couter=0;
sprintf((char *)str_str, "Error\r\n");
HAL_UART_Transmit(&huart1,(unsigned char *)str_str, strlen((char *)str_str), 50);
}
return ax;
}
Error1:
sprintf((char *)str_str, "Error\r\n");
HAL_UART_Transmit(&huart1,(unsigned char *)str_str, strlen((char *)str_str), 50);
memset((char*)buffe,0,sizeof((unsigned char*)buffe));
couter = 0;
然后提取车的种类和型号,保存每一部分的时间,然后判断时间是否合格,我们用goto语句来进行错误输出.
如果没有相同的车,把内容存到车库(结构体数组)
空闲车位检查:
判断是那种类型的车,最后清空串口接收缓存的数组buffe,以便于第二次进入数据
车库里面有
这就是整层逻辑,大家有什么疑问,可以在留言区发表意见,我们一起讨论,一起学习哦