题目
CubeMX配置
引脚配置
ADC2(PB15)配置
题目中要求使用R37电位器,将PB15配置为ADC2_IN15
定时器配置
使用TIM4作为按键定时器,TIM6为计时定时器,f=80M/8000/1000=10Hz,因此计一次为0.1s。
代码实现
初始化
//led函数
void led_disp(unsigned char dsled){
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,dsled<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void led_on(uint16_t led_pin){
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,led_pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void led_down(uint16_t led_pin){
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,led_pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
//adc初始化
double getADC(ADC_HandleTypeDef *pin){ //adc获取函数
unsigned int adc;
HAL_ADC_Start(pin);
adc = HAL_ADC_GetValue(pin);
return adc*3.3/4096;
}
//key初始化
struct keys{
unsigned char judge_sta;
bool key_sta;
bool single_flag;
unsigned int key_time;
};
struct keys key[4]={0,0,0,0};
int time1=0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM4)
{
key[0].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(key[i].judge_sta)
{
case 0:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=1;
key[i].key_time=0;
}
}
break;
case 1:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=2;
key[i].single_flag=1;
}
else
key[i].judge_sta=0;
}
break;
case 2:
{
if(key[i].key_sta==1)
{
key[i].judge_sta=0;
}
}
break;
}
}
}
if(htim->Instance==TIM6)
{
time1++; //计时
}
}
//uart初始化
char rxdata[30];
uint8_t rxda;
unsigned char rx_pointer;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rxdata[rx_pointer++] = rxda;
HAL_UART_Receive_IT(&huart1,&rxda,1);
}
测距函数
//测距函数distance_cal
void distance_cal(void){
if(getADC(&hadc2)<=3)//当V37<=3V时,distance=100*V37
{
distance = getADC(&hadc2)*100;
}
if(getADC(&hadc2)>3)//当V37>3V时,distance=300
distance = 300;
}
LCD显示
//lcd显示函数
void lcd_pro(void){
//显示界面
if(view == 1)
{
LCD_DisplayStringLine(Line1,(uint8_t *)" DATA");
//导航方向
sprintf(text," N:%s",direction);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
//与前车距离
sprintf(text," D:%.1f ",distance);
LCD_DisplayStringLine(Line4,(uint8_t *)text);
}
//偏离方向界面
if(view == 0)
{
LCD_DisplayStringLine(Line4,(uint8_t *)" WARN");
}
}
按键功能
//按键功能函数
void key_pro(void){
if(view == 0)
{
if(key[0].single_flag==1) //B1按下,界面切换,导航方向变为S,发送Success
{
LCD_Clear(Black);
view = 1;
direction[0] = 'S';
sprintf(text,"Success\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
key[0].single_flag=0;
}
//偏离导航界面中B3,B4失效
key[2].single_flag=0;
key[3].single_flag=0;
}
if(view == 1)
{
if(key[0].single_flag==1)//显示界面中,B1失效(按B1不会产生标志位干扰后面)
{
key[0].single_flag=0;
}
if(direction[0] == 'L')//接收到"L"
{
HAL_TIM_Base_Start_IT(&htim6);//启用定时器6开始计时
HAL_UART_AbortReceive(&huart1);//中断接收(题目中标明5s内不可重复改变导航方向)
if(key[2].single_flag==1&&time1<=50){//5s内按下B3的情况
HAL_UART_Receive_IT(&huart1,&rxda,1);//开启接收
sprintf(text,"Success\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
direction[0] = 'S';//改成直行
key[2].single_flag=0;
time1=0;
rx_pointer=0;
HAL_TIM_Base_Stop_IT(&htim6);//停止定时器6计时
}
if(time1>50)//未在5s内按下B3的情况
{
HAL_UART_Receive_IT(&huart1,&rxda,1);
LCD_Clear(Black);
view = 0;
time1 =0;
sprintf(text,"Warn\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
HAL_TIM_Base_Stop_IT(&htim6);//停止定时器6计时
}
}
if(direction[0] == 'R')//接收到"R",与"L"一样
{
HAL_TIM_Base_Start_IT(&htim6);
HAL_UART_AbortReceive(&huart1);
if(key[3].single_flag==1&&time1<=50){
HAL_UART_Receive_IT(&huart1,&rxda,1);
sprintf(text,"Success\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
direction[0] = 'S';
key[3].single_flag=0;
time1=0;
rx_pointer=0;
HAL_TIM_Base_Stop_IT(&htim6);
}
if(time1>50)
{
HAL_UART_Receive_IT(&huart1,&rxda,1);
LCD_Clear(Black);
view = 0;
time1 =0;
sprintf(text,"Warn\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
HAL_TIM_Base_Stop_IT(&htim6);
}
}
}
}
LED显示
//led显示函数
void led_pro(void){
if(view==0)
led_disp(0x80);//偏离导航界面时LD8亮
if(view==1)
{
led_down(GPIO_PIN_15);
if(direction[0] == 'L')//0.1s闪烁
{
if(time1%2==0)
led_on(GPIO_PIN_8);
if(time1%2==1)
led_down(GPIO_PIN_8);
}
if(direction[0] == 'R')//0.1s闪烁
{
if(time1%2==0)
led_on(GPIO_PIN_9);
if(time1%2==1)
led_down(GPIO_PIN_9);
}
}
}
串口函数
//串口发送接收函数
void uart_rx_pro(void)
{
if(view==1)
{
if(rx_pointer>0)
{
if(rx_pointer==1)
{
if(rxda=='L')
{
direction[0] = 'L';
}
else if(rxda=='R')
{
direction[0] = 'R';
}
else if(rxda!='L'&&rxda!='R')
{
sprintf(text,"ERROR\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
}
}
}
if(rx_pointer==0)
{
if(key[2].single_flag==1||key[3].single_flag==1){
sprintf(text,"Warn\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
view=0;
LCD_Clear(Black);
key[2].single_flag=0;
key[3].single_flag=0;
}
}
rx_pointer=0;
memset(rxdata,0,1);
}
if(view==0)
{
if(rx_pointer>0)
{
sprintf(text,"WAIT\r\n");
HAL_UART_Transmit(&huart1,(uint8_t *)text,strlen(text),50);
}
rx_pointer=0;
memset(rxdata,0,1);
}
}
主函数
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
distance_cal();
key_pro();
uart_rx_pro();
lcd_pro();
led_pro();
}
/* USER CODE END 3 */