因为把STM32这块单片机的资源都学完了,也就找了份真题来做做,在网上记录一下,一开始自己做是完完全全卡在串口那里了,完全不知道怎么做,之后去看了一下教程,虽然但是,在里面还是学到了很多的知识点的。
这一届,除了串口那一部分比较难,其它都还挺简单的了。。
用到的变量
/* 按键变量*/
__IO uint32_t key_uwTick;
uint8_t ucKey_Val,ucKey_Down,ucKey_Up,ucKey_Old;
/* LED变量*/
__IO uint32_t led_uwTick;
uint8_t ucled;
/* LCD变量*/
__IO uint32_t lcd_uwTick;
uint8_t lcd_disp_string[21];
/* 串口相关变量*/
__IO uint32_t usart_uwTick;
//uint8_t Tx_dat[20];
uint8_t Rx_dat;
uint8_t Rx_buf[200];//用于接收22个字符的缓冲
uint8_t Rx_count;//索引,记录接收了多少个数据
uint8_t str_str[40];
_Bool interface;
uint8_t CNBR;
uint8_t VNBR;
uint8_t IDEL = 8;
float CNBR_Price = 3.50;
float VNBR_Price = 2.00;
_Bool PA7_Staus;
typedef struct{
uint8_t type[5];
uint8_t id[5];
uint8_t year_in;
uint8_t month_in;
uint8_t day_in;
uint8_t hour_in;
uint8_t min_in;
uint8_t sec_in;
_Bool notEmpty;
} Car_Data_Storage_Type;
/* 数据库构建完毕,用于存储8个进来的车的信息*/
Car_Data_Storage_Type Car_Data_Storage[8];
先把外设的函数和.c文件写好
led_key.c
#include "led_key.h"
void Led_Disp(uint8_t ucled)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, 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,ucled<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
uint8_t Key_Scans(void)
{
uint8_t ucKey_val = 0;
if(key1 == Key_Down)
ucKey_val = 1;
if(key2 == Key_Down)
ucKey_val = 2;
if(key3 == Key_Down)
ucKey_val = 3;
if(key4 == Key_Down)
ucKey_val = 4;
return ucKey_val;
}
外设的处理函数
void Key_Proc(void)
{
if(uwTick - key_uwTick < 50)
return;
key_uwTick = uwTick;
ucKey_Val = Key_Scans();
ucKey_Down = ucKey_Val & (ucKey_Old ^ ucKey_Val);
ucKey_Up = ~ucKey_Val & (ucKey_Old ^ ucKey_Val);
ucKey_Old = ucKey_Val;
switch(ucKey_Down)
{
case 1:
interface ^= 0x1;
break;
case 2:
if(interface)
{
VNBR_Price += 0.5f;
CNBR_Price += 0.5f;
}
break;
case 3:
if(interface)
{
if((VNBR_Price - 0.5f)> 0)
{
VNBR_Price -= 0.5f;
CNBR_Price -= 0.5f;
}
}
break;
case 4:
PA7_Staus ^= 0x1;
if(PA7_Staus)
__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1, 100);//强制配置成PWM电平
else
__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1, 0);
break;
}
}
void Led_Proc(void)
{
if(uwTick - led_uwTick < 200)
return;
led_uwTick = uwTick;
if(IDEL)
ucled |= 0x01;
else
ucled &= (~0x01);
if(PA7_Staus)
ucled |= 0x02;
else
ucled &= (~0x02);
Led_Disp(ucled);
}
void Lcd_Proc(void)
{
if(uwTick - lcd_uwTick < 200)
return;
lcd_uwTick = uwTick;
if(interface == 0)
{
LCD_DisplayStringLine(Line0,(u8 *)" Data ");
sprintf((char *)lcd_disp_string," CNBR:%d ",CNBR);
LCD_DisplayStringLine(Line4,lcd_disp_string);
sprintf((char *)lcd_disp_string," VNBR:%d ",VNBR);
LCD_DisplayStringLine(Line6,lcd_disp_string);
sprintf((char *)lcd_disp_string," IDEL:%d ",IDEL);
LCD_DisplayStringLine(Line8,lcd_disp_string);
}
else
{
LCD_DisplayStringLine(Line0,(u8 *)" Pata ");
sprintf((char *)lcd_disp_string," CNBR:%.2f ",CNBR_Price);
LCD_DisplayStringLine(Line4,lcd_disp_string);
sprintf((char *)lcd_disp_string," VNBR:%.2f ",VNBR_Price);
LCD_DisplayStringLine(Line6,lcd_disp_string);
LCD_DisplayStringLine(Line8,(u8 *)" ");
}
}
在main函数中初始化
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1, 0);//强制配置成低电平
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1); //PA7
/* 串口接收中断打开*/
HAL_UART_Receive_IT(&huart1,(uint8_t *)(&Rx_dat),1);//执行完这个之后会进入下面的中断回调函数
之后就是处理串口了,首先得判断接受的数据个数和格式是否合法,再通过判断车的类型判断车有没有进(这时候就需要从那一串发送的数据中提取车的类型和id),如果车还没进入,就得把车放进去,让车的类型++,同时空位要--;如果车已经进来了,就要判断车在里面的时间了,这里用的方法是把时间全都转换成秒,再相减,得到结果再通过串口发送出去,之后还得让车的类型-1,空位+1,最后清空该位置的所有内容,全清为0。
第一步:判断发送的22个字符是否合法。
_Bool CheckCmd(uint8_t* str)
{
if(Rx_count != 22)
return 0;
if(((str[0]=='C')||(str[0]=='V'))&&(str[1]=='N')&&(str[2]=='B')&&(str[3]=='R')&&(str[4]==':')&&(str[9]==':'))
{
uint8_t i;
for(i = 10; i < 22; i++)
{
if((str[i]>'9')||(str[i]<'0'))
return 0;
}
return 1;//表示接受的数据没问题
}
}
第二步:判断车的类型(所以要先从长的字符串中提取短的字符串,也即是车的类型)
void substr(uint8_t* d_str,uint8_t* s_str,uint8_t loc,uint8_t len)
{
uint8_t i = 0;
for(i = 0; i < len; i++)
{
d_str[i] = s_str[loc+i];
}
d_str[len] = '\0';
}
第三步:判断车是否在里面(判断车的id)
uint8_t isExist(uint8_t* str)
{
uint8_t i = 0;
for(i = 0; i < 8; i++)
{
if((strcmp((const char *)str,(const char *)Car_Data_Storage[i].id)) == 0)//字符串匹配,表示库里面有这辆车(车在库里)
{
return i;
}
}
return 0xff; //车不在库里,返回0xff
}
第四步:如果车不在里面,判断哪个位置有空位
uint8_t findLocate(void)
{
uint8_t i = 0;
for(i = 0; i < 8; i++)
{
if(Car_Data_Storage[i].notEmpty == 0)
return i;
}
return 0xff;
}
串口处理函数
void Usart_Proc(void)
{
if(uwTick - usart_uwTick < 100)
return;
usart_uwTick = uwTick;
// sprintf((char *)lcd_disp_string," test:%d ",CheckCmd(Rx_buf));
// LCD_DisplayStringLine(Line9,lcd_disp_string);
if(CheckCmd(Rx_buf))//数据个数和格式是否合法
{
uint8_t car_id[5];
uint8_t car_type[5];
uint8_t year_temp,month_temp,day_temp,hour_temp,min_temp,sec_temp;
year_temp = ((Rx_buf[10] - '0')*10) + (Rx_buf[11] - '0');
month_temp = (((Rx_buf[12] - '0')*10) + (Rx_buf[13] - '0'));
day_temp = (((Rx_buf[14] - '0')*10) + (Rx_buf[15] - '0'));
hour_temp = (((Rx_buf[16] - '0')*10) + (Rx_buf[17] - '0'));
min_temp = (((Rx_buf[18] - '0')*10) + (Rx_buf[19] - '0'));
sec_temp = (((Rx_buf[20] - '0')*10) + (Rx_buf[21] - '0'));
if((month_temp>12)||(day_temp>31)||(hour_temp>23)||(min_temp>59)||(sec_temp>59))//验证日期和时间是否合法
{
goto SEND_ERROR;
}
substr(car_id,Rx_buf,5,4);//提取车的id
substr(car_type,Rx_buf,0,4);//提取车的类型
// sprintf((char *)lcd_disp_string, " test:%x",isExist(car_id));
// LCD_DisplayStringLine(Line9, lcd_disp_string);
/** 车还没进入*/
if(isExist(car_id) == 0xff)
{
uint8_t locate = findLocate();//找到哪个地方是空的
if(locate == 0xff)
{
goto SEND_ERROR;
}
substr(Car_Data_Storage[locate].type,car_type,0,4);//把当前车的类型存入
substr(Car_Data_Storage[locate].id,car_id,0,4);//把当前车的id存入
Car_Data_Storage[locate].year_in = year_temp;
Car_Data_Storage[locate].month_in = month_temp;
Car_Data_Storage[locate].day_in = day_temp;
Car_Data_Storage[locate].hour_in = hour_temp;
Car_Data_Storage[locate].min_in = min_temp;
Car_Data_Storage[locate].sec_in = sec_temp;
Car_Data_Storage[locate].notEmpty = 1;
if(Car_Data_Storage[locate].type[0] == 'C')
CNBR++;
else if(Car_Data_Storage[locate].type[0] == 'V')
VNBR++;
IDEL--;
}
/** 车已经在库里,进来了*/
else if(isExist(car_id) != 0xff)
{
int64_t Second_derta;//核算小时的差值
uint8_t in_locate = isExist(car_id);//记录在数据库中的位置
if(strcmp((const char *)car_type,(const char *)Car_Data_Storage[in_locate].type) != 0) //不匹配
{
goto SEND_ERROR;
}
Second_derta = (year_temp - Car_Data_Storage[in_locate].year_in)*365*24*60*60 + (month_temp - Car_Data_Storage[in_locate].month_in)*30*24*60*60+\
(day_temp - Car_Data_Storage[in_locate].day_in)*24*60*60 + (hour_temp - Car_Data_Storage[in_locate].hour_in)*60*60 + \
(min_temp - Car_Data_Storage[in_locate].min_in)*60 + (sec_temp - Car_Data_Storage[in_locate].sec_in);
if(Second_derta < 0)//出去的时间超前进去的时间
{
goto SEND_ERROR;
}
Second_derta = (Second_derta + 3599)/3600;
sprintf((char *)str_str,"%s:%s:%d:%.2f\r\n",Car_Data_Storage[in_locate].type,Car_Data_Storage[in_locate].id,(uint32_t)Second_derta,Second_derta*(Car_Data_Storage[in_locate].id[0] == 'C' ? CNBR_Price:VNBR_Price));
HAL_UART_Transmit(&huart1,(uint8_t *)str_str,sizeof(str_str),50);
if(Car_Data_Storage[in_locate].type[0] == 'C')
CNBR--;
else if(Car_Data_Storage[in_locate].type[0] == 'V')
VNBR--;
IDEL++;
memset(&Car_Data_Storage[in_locate],0,sizeof(Car_Data_Storage[in_locate]));//清空该位置所有内容,为0
}
goto CMD_YES;
SEND_ERROR:
sprintf((char *)str_str, "Error\r\n");
HAL_UART_Transmit(&huart1,(unsigned char *)str_str, sizeof(str_str), 50);
CMD_YES:
memset(&Rx_buf[0],0,sizeof(Rx_buf));
Rx_count = 0;
}
}
当然,我们发送的数据得存起来。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
Rx_buf[Rx_count] = Rx_dat;
Rx_count++;
HAL_UART_Receive_IT(&huart1,(uint8_t *)(&Rx_dat),1);
}