【Mr.chen|开发日记Nov.5】语音交互智能物联网小车设计(2)
Mr.chen 发布于2017-12-12 14:52 浏览:1846 回复:0
0
收藏

本帖子 针对智能小车外围传感器进行演示编程




PM2.5传感器

blob.png


夏普光学灰尘传感器(GP2Y1014AU0F)在检测非常细的颗粒,如香烟烟雾,是特别有效的,并且是常用的空气净化器系统。

    该装置中,一个红外发光二极管和光电晶体管,对角布置成允许其检测到在空气中的灰尘反射光。传感器中心有个洞可以让空气自由流过,定向发射LED光,通过检测经过空气中灰尘折射过后的光线来判断灰尘的含量。

    这里通过读取输出脚的模拟电压来判读颗粒浓度,用到stm32 内部ADC转换。

*********************************************
ADC1初始化程序  PB1口用于LED信号触发
*********************************************
 
void Adc_Init(void)
{ 
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB  , ENABLE );
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC 6分频 72/6=12<14MHz 不应许采用频率大于14Mhz
 
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;   //配置PA1引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;// 配置端口为模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //  将配置信息送入寄存器
ADC_DeInit(ADC1); //  ADC1缺省
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //ADC配置独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE;  //启用单通道模式
ADC_InitStructure.ADC_ContinuousConvMode =DISABLE; //失能单次转化
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//
设置ADC转换为软件转换,非外部触发转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采样数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1;  //顺序转换通道数
ADC_Init(ADC1, &ADC_InitStructure);  //  将数据送入ADC寄存器完成初始化
ADC_Cmd(ADC1, ENABLE);  //  使能ADC1
ADC_ResetCalibration(ADC1);  //  开启复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待校准完成
ADC_StartCalibration(ADC1);  //   开启采样校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准完成
 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;   //配置引脚1
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//引脚切换速度为50M
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//配置引脚为开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);//将配置数据送入GPIOB寄存器
GPIO_SetBits(GPIOB, GPIO_Pin_1 );// 将PB1置为高电平
 
}
      
 
//*******************************************************************
   进行一次ADC转化:
CH=通道  S=规则序列
//*******************************************************************
u16 Get_Adc(u8 ch,u8 s)
{
 
ADC_RegularChannelConfig(ADC1, ch, s, ADC_SampleTime_239Cycles5 );// 设置指定 ADC 的规则组通道,设置它们的转化顺序和采样时间
 
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能软件转换
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));等待转换完成
 
return ADC_GetConversionValue(ADC1); 返回转换后的值
}
 
 
//*******************************************************************
//得到 ADC单通道多次平均值
//ch=通道 S为规则序列 time=n次读取求平均值
//*******************************************************************
 
u16 Get_Adc_Average(u8 ch,u8 s,u8 times)
{
     float temp_val=0;
     float pm;
     u8 t;
     u8 z=0;
     for(t=0;t300)  //软件滤波 滤掉采样值<300的数据
         {
              temp_val+=Get_Adc(ch,s); //累计求和
                   }
         else
         {
              z++;         //对100)   //当杂波数据达到100次时废弃所有数据重新采样
              return 0;
            }
     delay_us(280);      //延时280us
           GPIO_SetBits(GPIOB, GPIO_Pin_1 );     //将PB1拉高
     delay_us(9680); //延时9680us
     }
          temp_val=temp_val/times; //最终采样值=采样数据总和/采样次数 
          return temp_val;  //程序返回最终转换值
}


 串口控制插卡SD卡语音模块:用于语音播报,事先用软件合成固定的语音,通过串口指令可以操作播放指定语音文件。

blob.png

blob.png

Stm32串口1配置代码如下:

void Usart1_Init(unsigned int baud)
{
         GPIO_InitTypeDef gpioInitStruct; //定义机构数组
     USART_InitTypeDef usartInitStruct;//
     NVIC_InitTypeDef nvicInitStruct;//
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    //开启A  管脚时钟                         
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);  //开启USart1时钟
     gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//配置复用推挽输出      
     gpioInitStruct.GPIO_Pin = GPIO_Pin_9;   //配置第9脚             
         gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;//设置切换速度         
          GPIO_Init(GPIOA, &gpioInitStruct);    //将数据送入GPIOA寄存器          
        gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入模式        
        gpioInitStruct.GPIO_Pin = GPIO_Pin_10;  //配置第10脚                   
        gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz; //速度50Mhz      
        GPIO_Init(GPIOA, &gpioInitStruct); //送入GPIOA寄存器               
        usartInitStruct.USART_BaudRate = baud;//波特率设置为baud变量
    usartInitStruct.USART_HardwareFlowControl =   USART_HardwareFlowControl_None;  //无硬件数据流控制    
     usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发  模式
     usartInitStruct.USART_Parity = USART_Parity_No;//无奇偶校验              
     usartInitStruct.USART_StopBits = USART_StopBits_1;   //一个停止位      
     usartInitStruct.USART_WordLength = USART_WordLength_8b;//8位数据位    
      USART_Init(USART1, &usartInitStruct);将配置信息送入usart1寄存器
     USART_Cmd(USART1, ENABLE);        
}

定义:

         uint8_t stop[ ]={0x7e,0x03,0x1e,0x1d,0xef,0x00};  //停止命令

串口输出:   printf(stop);

注:前提是串口重定义过,才能使用printf函数。(网上搜索串口重定义的相关知识)    否则 直接使用stm32f10x标准库里面的USART_SendData();函数进行逐个字节输出.

blob.png

舵机通过控制器发送不同占空比的PWM来改变它转动的角度,每个角度对于一个特定的频率的PWM,关于stm32  pwm的配置如下:

*************************************************************
初始化定时器4 为PWM模式
************************************************************
void TIM4_PWM_Init(u16 arr,u16 psc)
{                                               
       GPIO_InitTypeDef GPIO_InitStructure; //定义数组
       TIM_TimeBaseInitTypeDef  
       TIM_TimeBaseStructure;
       TIM_OCInitTypeDef  TIM_OCInitStructure;
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//开tim4时钟       
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  |      RCC_APB2Periph_AFIO, ENABLE);   //开GPIOB时钟 开复用功能时钟
       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; //配置8,9引脚
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //配置复用推挽输出
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;//切换速度为10Mhz
       GPIO_Init(GPIOB, &GPIO_InitStructure); //将配置信息跟新到GPIOB寄存器
            TIM_TimeBaseStructure.TIM_Period = arr;  //自动重装载值
       TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频系数
       TIM_TimeBaseStructure.TIM_ClockDivision = 0;  //设置时钟分割
       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式
       TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据配置信息初始化tim4
       TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //配置为pwm2模式
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较使能
       TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性为高
       TIM_OC3Init(TIM4, &TIM_OCInitStructure);   //初始化tim4 第3通道
 
       TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //配置PWM2模式
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较使能
       TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性为高
        TIM_OC4Init(TIM4, &TIM_OCInitStructure);//初始化time4 第4通道
       TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);//使能预装载寄存器
       TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);     
       TIM_Cmd(TIM4, ENABLE);        //启动tim4 时钟                                                   
}

通过库标准函数改变舵机转动角度:  TIM_SetCompare3(TIM4,1870);

                                                                  TIM_SetCompare4(TIM4,1880)



blob.png

超声波测距用到stm32定时器输入捕获功能配置过程如下:

*********************************************************
初始化定时器2为捕获模式
********************************************************
void TIM2_Cap_Init(u16 arr,u16 psc)
{            
       TIM_ICInitTypeDef  TIM2_ICInitStructure; 
       GPIO_InitTypeDef GPIO_InitStructure;
       TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
      NVIC_InitTypeDef NVIC_InitStructure;  
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开定时器2时钟
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);  //开GPIOA时钟 开复用时钟
       
       GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0 ;  //配置0管脚
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 下拉输入
       GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA0
       GPIO_ResetBits(GPIOA,GPIO_Pin_0);    //将PA0输出为低电平                                 
       TIM_TimeBaseStructure.TIM_Period = arr;    //重装载值
       TIM_TimeBaseStructure.TIM_Prescaler =psc;     //预分频系数
       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数
       TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器2
      TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //配置通道1
      TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕获
      TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 
      TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;       //不分频
           TIM2_ICInitStructure.TIM_ICFilter =0x00;           //捕获不滤波
      TIM_ICInit(TIM2, &TIM2_ICInitStructure);
       NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //设置tim2中断       
       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //抢占优先级
       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级
       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 使能IRQ通道
       NVIC_Init(&NVIC_InitStructure);  //根据配置信息初始化寄存器
       TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);//使能中断
       TIM_Cmd(TIM2,ENABLE );         //使能定时器2
}
*************************************************************
       定时器2中断服务程序
*************************************************************
       void TIM2_IRQHandler(void)
       {               
              if((TIM2CH1_CAPTURE_STA&0X80)==0)
              {
                     if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
                     {         
                            if(TIM2CH1_CAPTURE_STA&0X40)
                            {
                                   if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)
                                   {
                                          TIM2CH1_CAPTURE_STA|=0X80;
                                          TIM2CH1_CAPTURE_VAL=0XFFFF;
                                   }else TIM2CH1_CAPTURE_STA++;
                            }      
                       }
                     if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) 
               {   
                           if(TIM2CH1_CAPTURE_STA&0X40)          
                        {                         
                            TIM2CH1_CAPTURE_STA|=0X80;          
                             TIM2CH1_CAPTURE_VAL=TIM_GetCapture1(TIM2);
                                                                                                                           TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);  
                     }else                                              
                     {
                                   TIM2CH1_CAPTURE_STA=0;            
                                   TIM2CH1_CAPTURE_VAL=0;
                                   TIM2CH1_CAPTURE_STA|=0X40;   
                                  TIM_SetCounter(TIM2,0);
                                  TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);        
                     }                
              }                                                                       
          }
              TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); 
              TIM2_1CAP();
       }
   ***********************************************************
       距离转化函数
  ***********************************************************
 void TIM2_1CAP()
       {
              if(TIM2CH1_CAPTURE_STA&0X80)
              {
               temp=TIM2CH1_CAPTURE_STA&0X3F;
               temp*=65536;
              temp+=TIM2CH1_CAPTURE_VAL;
             temp=temp*17;
              z=temp/1000;
                TIM2CH1_CAPTURE_STA=0; 
             }
       }


收藏
点赞
0
个赞
TOP