蓝桥杯嵌入式第十二届决赛试题及其参考

写在前面

涉及频率捕获,多路pwm捕获,led扫描,按键扫描,ad采样,lcd液晶驱动,队列处理数据,排序输出。

工程链接

链接:https://pan.baidu.com/s/1YPu9g7w3-JNVrgv5iPo7qg 
提取码:yzh1

主要代码参考



#include "work.h"
#include "stdbool.h"
#include "string.h"
#include "stdlib.h"
u8 LEDINDEX[] = { 0X00,1<<0,1<<1,1<<2,1<<3,1<<4,1<<5,1<<6,1<<7 };
u8 LEDDT[8] = {0};
u8 adct= 0;
u16 adcbuf[2];
u8 ledt = 0;
 #define READB1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
 #define READB2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
 #define READB3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
 #define READB4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);

typedef struct key
{
    u16 keytime;
    u8 keystate;
    bool sflag;
    bool lflag;
    bool state;
    
    
    
}key;


typedef struct mypuls{
  
 u32 ts; //记录的脉冲值
 u32 currentfreq; //测得频率
 u8  flag; //开始信号/结束信号
 u16 time; //记录的时间   

} puls;


typedef struct mypwm{
    
    u32 firstrisingcnt;
    u32 secondrisingcnt;
    u32 fallingcnt;
    u32 validcnt; //有效计数值对应于脉宽
    float freq;
    float duty;
    u16 updatetimes;
    u8 state;
    
    
    
} pwms;


pwms mpwms[2] ={0};
puls m1 = {0};
key keys[4]={0};

bool uic = false;  //数据 , 参数
bool mode = false ; //  A -B
u8 pax = 20;
u8 pbx = 20;
u16 pf = 1000;


u32 freq  =0;
 
u8 ax,bx; //角度变化量
float ag,bg; //角度

typedef struct mqueen
{
    float buf[5];
    u8 s;
    
        
}mqueen;


mqueen  queen[2]= { 0 };

bool isflash = false; //是否刷新数据
u8 rxbuf[100];

u16 testtime  = 0; //测试输出
void key_scan()
{
    keys[0].state = READB1;
    keys[1].state = READB2;
    keys[2].state = READB3;
    keys[3].state = READB4;
    for(int i = 0 ; i < 4; i++)
    {
        
        switch(keys[i].keystate)
        {
            
            case 0:
                if(!keys[i].state)keys[i].keystate = 1;
                break;
            case 1:
                 if(!keys[i].state)keys[i].keystate = 2;
                 else keys[i].keystate = 0;
                break;
            case 2:
                  if(!keys[i].state)
                  {
                      
                  }
                  else{
                      
                      keys[i].sflag = 1;
                      keys[i].keystate =0;
                      
                  }
                break;
            
            
        }
        
    }
    
}



void keyop(void)
{
    if( keys[0].sflag )
    {
        
        uic =!uic;
        keys[0].sflag =0 ;
    }
    else if(keys[1].sflag)
    {
        
        keys[1].sflag = 0;
        if(!uic)return;
        if(pax == 60) pax = 10;
        else 
            pax +=10;
        if(pbx == 60) pbx = 10;
        else pbx += 10;
        
        
    }
    else if(keys[2].sflag)
    {
        keys[2].sflag = 0;
        if(uic){
            
                if(pf == 10000) pf =1000;
                 else pf+=1000;    
        }
        else 
        {
            mode = !mode;
            
        }
    }
    else if(keys[3].sflag)
    {
        keys[3].sflag = 0;
        
        if(!mode) isflash = true;
        
        //数据刷新
        
    }
    
}

 //从小到大快速排序
void quick_sort(float * arr,int left,int right)
{

        if(left >= right) return;
        int i = left-1;
        int j = right+1;
        float mid = arr[(left+right) /2];
        
        while(i < j)
        {
            
            do i++;while(arr[i] < mid);
            do j--;while(arr[j] > mid);
            
            if(i < j)
            {
                float temp =arr[i];
                arr[i] =arr[j];
                arr[j] = temp;
                
            }
                
            
            
        }
        quick_sort(arr,left,j);
        quick_sort(arr,j+1,right);

}    
    
    
void flashdata(void)
{
    
    
    //刷新数据
    if(isflash)
    {
        int temp = ag;
        if(mpwms[0].duty >= 90) ag= 180;     
        else 
        {
            
           ag = 10+2.25f*mpwms[0].duty;
            
        }    
        temp = ag-temp;
        ax = abs(temp);
        
         if(queen[0].s ==5)
         {
             u8 j =1;
             while(j <= 4)
             {
                 
                 queen[0].buf[j-1] =queen[0].buf[j];
                 j++;
                 
             }
              queen[0].buf[4] = ag; //越后越新
         }
         else  //未装满
         {
             
             queen[0].buf[queen[0].s++] =ag;
             
         }
        
        
        temp = bg;
        if(mpwms[1].duty >=90) bg = 180;
        else 
        {
            
           bg = 10+2.25f*mpwms[1].duty;
            
        }
          
        temp  =  bg-temp;
        bx    =  abs(temp);
        
        
          if(queen[1].s ==5)
         {
             u8 j =1;
             while(j <= 4)
             {
                 
                 queen[1].buf[j-1] =queen[1].buf[j];
                 j++;
                 
             }
              queen[1].buf[4] = bg; //越后越新
         }
         else  //未装满
         {
             
             queen[1].buf[queen[1].s++] =bg;
             
         }
        
        
        
        freq =  m1.currentfreq;
        
        
        
        isflash =false;
        
    }
    
}

void getadc()
{
    
    if(!mode) return ;
    static  u16 oldval = 0;
    if(adct > 50 ) 
    {
            adct = 0;
        
         u16 newval = (adcbuf[0]+adcbuf[1])/2;    
         if(newval > 2000 && oldval < 2000) {
             isflash =true;
         }
             
          oldval = newval ;
    }
    
}
 
 void led_display( u8 ds)
{
     
    HAL_GPIO_WritePin(GPIOC,0XFF<<8,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,ds<<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 ledop(void)
{
    
    if(ax > pax) LEDDT[0] =1;
    else LEDDT[0] = 0;

    if(bx > pbx) LEDDT[1] = 2;
    else LEDDT[1] = 0;

    if(freq > pf) LEDDT[2] =3;
    else LEDDT[2] =0;

    if(!mode) LEDDT[3] =4;
    else LEDDT[3] =0;
    
    if( abs((int)(90+bg-ag)) < 10    ) LEDDT[4] =5;
    else LEDDT[4] = 0;
    

}
 
 void myinit(void)
 {
     led_display(0);
       
 }
 
 
 void led_scan(void)
{
    
    if(ledt > 50)
    {
        
        ledt = 0;
    
    u8 temp = 0;
    for(int i = 0 ; i < 8 ;i++)temp|=LEDINDEX[LEDDT[i]];
    led_display(temp);
    
    ledop();
        
    }
     
}


void lcd_display(void)
{
     
    
    
    //测试频率
//    if(testtime > 1000)
//    {
//        
//    printf("pwm1:%.2f  - %.2f\r\n",mpwms[0].freq,mpwms[0].duty);
//    printf("pwm2:%.2f  - %.2f\r\n",mpwms[1].freq,mpwms[1].duty);   
//    testtime  = 0;
//    }
     
     char temp[131];
     if(!uic)
     {
         
        LCD_DisplayStringLine(Line1,"        DATA        ");
         sprintf(temp,"   a:%.1f                   ",ag);
         LCD_DisplayStringLine(Line2,temp);
          sprintf(temp,"   b:%.1f                          ",bg);
         LCD_DisplayStringLine(Line3,temp);
          sprintf(temp,"   f:%dHz                           ",freq);
         LCD_DisplayStringLine(Line4,temp);
         
         
         sprintf(temp,"   ax:%d                          ",ax);
         LCD_DisplayStringLine(Line6,temp);
         
           sprintf(temp,"   bx:%d                             ",bx);
         LCD_DisplayStringLine(Line7,temp);
         
         sprintf(temp,"   mode:%c                         ",!mode?'A':'B');
         LCD_DisplayStringLine(Line8,temp);
         
     }
     else 
     {
         LCD_DisplayStringLine(Line1,"        PARA                     ");
         sprintf(temp,"   Pax:%d                             ",pax);
         LCD_DisplayStringLine(Line2,temp);
         sprintf(temp,"   Pbx:%d                             ",pbx);
         LCD_DisplayStringLine(Line3,temp);
          sprintf(temp,"   Pf:%d                              ",pf);
         LCD_DisplayStringLine(Line4,temp);
         
         
       
            LCD_DisplayStringLine(Line6,"                              ");
            LCD_DisplayStringLine(Line7,"                              ");
            LCD_DisplayStringLine(Line8,"                               ");
     }
            
}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
    
    if(htim->Instance == TIM6)
    {
        
        adct++;
        ledt++;
        testtime++;
        if(m1.flag == 0) m1.flag = 1; //第一次进来
        else if(m1.flag == 1){ 
            
          if( ++m1.time == 1000) //测1s内
          {
              
              //已经测了1s
              m1.time = 0;
              m1.flag = 0;
              m1.currentfreq = m1.ts;
              m1.ts = 0;
              
          } 
            
            
        }
    }
    
    else if(htim->Instance == TIM7)
    {
        key_scan();
        
        
    }
    else if(htim->Instance == TIM3)
    {
        
        //两路的更新计数值自加1,这里实际上可以用一个代替
       mpwms[0].updatetimes++;
       mpwms[1].updatetimes++;
        
        
        
    }
    
}   



void Inputcapturehandle(pwms * cpwm,u32 cnt,TIM_HandleTypeDef *htim,u32 ch)
{
    
     u32 temp = 0;
     switch(cpwm->state)
    {   
        case 0:     //测量上升沿
        {    
                //开启下次为下降沿采样
                __HAL_TIM_SET_CAPTUREPOLARITY(htim, ch, TIM_INPUTCHANNELPOLARITY_FALLING); 
                //溢出计数值置为0
                cpwm->updatetimes = 0;
               //捕获第一次计数值
                cpwm->firstrisingcnt =cnt;
                //更新状态
                cpwm->state = 1;     
                break;
            
        }
         
        case 1:    //测量下降沿
        {
                    //开启下一次为上升沿采样
                 __HAL_TIM_SET_CAPTUREPOLARITY(htim, ch, TIM_INPUTCHANNELPOLARITY_RISING);      
                 //捕获下降沿的计数值
                cpwm->fallingcnt = cnt;
                 //计算有效计数值(考虑溢出)
                cpwm->validcnt =  (cpwm->updatetimes * htim->Instance->ARR)+ cpwm->fallingcnt-cpwm->firstrisingcnt;    
                 //溢出计数置为0
                cpwm->updatetimes  =0;  
                 //更新下一状态
                cpwm->state = 2;       
                        break;     
            
         }
               
     
        case 2:  //再次测量上升沿
            {
                //捕获第二次上升沿的计数值
                cpwm->secondrisingcnt = cnt;
                //计算两个上升沿之间的计数值(考虑溢出)
                temp =  cpwm->secondrisingcnt + (cpwm->updatetimes * htim->Instance->ARR) - cpwm->firstrisingcnt;
                //溢出计数值置为0
                cpwm->updatetimes = 0;
                //计算频率 = 定时器频率/一个PWM波的两个上升沿的计数值
                cpwm->freq = 1e6/temp;
                //计算占空比
                cpwm->duty = cpwm->validcnt*1.0f / temp *100;
                //更新状态
                cpwm->state = 0;
                
                    
            }   
            break;  
            
        
    }
               
}


void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    
    
 
    
    if(htim->Instance == TIM2)
    {
        
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
            
 
            //计算脉冲个数
            if(m1.flag == 1)  m1.ts++;
        
                     
        }
        
    }
    else if(htim->Instance ==  TIM3)
    {
        if(htim->Channel ==  HAL_TIM_ACTIVE_CHANNEL_1)
        {
            
            //进入到自己的中断回调函数中执行
            Inputcapturehandle(&mpwms[0],TIM3->CCR1,htim,TIM_CHANNEL_1);

            
        }
        else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
                 //进入到自己的中断回调函数中执行
           Inputcapturehandle(&mpwms[1],TIM3->CCR2,htim,TIM_CHANNEL_2);
        }
            
            
    }
        
        
}

  void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    
    if(huart->Instance ==USART1)     
    {
        
       if(!strcmp(rxbuf,"a?"))
       {
           printf("a:%.1f\r\n",ag);
       }
       else if(!strcmp(rxbuf,"b?"))
       {
           printf("b:%.1f\r\n",bg);
       }
       else if(!strcmp(rxbuf,"aa?"))
       {
          
           u8 temp = queen[0].s;
           if(temp){
               printf("aa:");
                   temp -=1;
                   for(int k = 0 ; k < temp ; k++)
                   {
                       printf("%.1f-",queen[0].buf[k]);
                   }
                   printf("%.1f\r\n",queen[0].buf[temp]);
            }
       }
       else if(!strcmp(rxbuf,"bb?"))
       {
           u8 temp = queen[1].s;
           if(temp){
                   temp -=1;
                    printf("bb:");
                   for(int k = 0 ; k < temp ; k++)
                   {
                       printf("%.1f-",queen[1].buf[k]);
                   }
                   printf("%.1f\r\n",queen[1].buf[temp]);
            }
           
       }
       else if(!strcmp(rxbuf,"qa?"))
       {
                   printf("qa:");
                   float buf[6];
                   int len = queen[0].s;
                   for(int k = 0; k < len;k++) buf[k]=queen[0].buf[k];
                   quick_sort(buf,0,len-1);
                   for(int k = 0; k < len-1 ; k++)printf("%.1f-",buf[k]);
                   printf("%.1f\r\n",buf[len-1]);
           
       }
       else if(!strcmp(rxbuf,"qb?"))
       {            
                   printf("qb:");
                   float buf[6];
                   int len = queen[1].s;
                   for(int k = 0; k < len;k++) buf[k]=queen[1].buf[k];
                   quick_sort(buf,0,len-1);
                   for(int k = 0; k < len-1 ; k++)printf("%.1f-",buf[k]);
                   printf("%.1f\r\n",buf[len-1]);
       }
       else 
       {
           printf("error\r\n");
       }
          
        memset(rxbuf,0x00,sizeof(rxbuf));
        extern UART_HandleTypeDef huart1;
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rxbuf,100);
    }
 
}




你可能感兴趣的:(蓝桥杯,stm32,嵌入式)