蓝桥杯嵌入式第十五届模拟考试一

题目

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 */

  • 44
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 86
    评论
评论 86
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值