donatello1996 发表于 2020-7-26 12:44

【STM32F769Discovery开发板试用】单总线DHT11驱动&ADC光照/接近传感器&串行驱动RGB

<p>&nbsp; &nbsp; &nbsp; &nbsp;本帖使用庆科Arduino扩展板的各个外设,测评STM32F769的单总线/AD/模拟串行总线的通信性能,使用扩展板的外设模块有DHT11模块,光敏电阻,红外接收头,P9813RGB彩灯模块。</p>

<p><br />
&nbsp; &nbsp; &nbsp; &nbsp;首先是DHT11单总线模块,这个直接参考网上代码即可:</p>

<pre>
<code>void DHT11_Rst(void)          
{               
        DHT11_IO_OUT();
DHT11_DQ_OUT(0);
Delay_ms(20);
DHT11_DQ_OUT(1);
        Delay_us(30);
}

unsigned char DHT11_Check()           
{   
        unsigned char retry=0;
        DHT11_IO_IN();
while (DHT11_DQ_IN&amp;&amp;retry&lt;100)
        {
                retry++;
                Delay_us(1);
        };       
        if(retry&gt;=100)return 1;
        else retry=0;
    while (!DHT11_DQ_IN&amp;&amp;retry&lt;100)
        {
                retry++;
                Delay_us(1);
        };
        if(retry&gt;=100)return 1;          
        return 0;
}

unsigned char DHT11_Read_Bit(void)                        
{
        unsigned char retry=0;
        while(DHT11_DQ_IN&amp;&amp;retry&lt;100)
        {
                retry++;
                Delay_us(1);
        }
        retry=0;
        while(!DHT11_DQ_IN&amp;&amp;retry&lt;100)
        {
                retry++;
                Delay_us(1);
        }
        Delay_us(40);
        if(DHT11_DQ_IN)return 1;
        else return 0;                  
}

unsigned char DHT11_Read_Byte(void)   
{      
    unsigned char i,dat;
    dat=0;
        for (i=0;i&lt;8;i++)
        {
                   dat&lt;&lt;=1;
          dat|=DHT11_Read_Bit();
    }                                                  
    return dat;
}

unsigned char DHT11_Read_Data(unsigned char *temp,unsigned char *humi)   
{      
        unsigned char buf;
        unsigned char i;
        DHT11_Rst();
        if(DHT11_Check()==0)
        {
                for(i=0;i&lt;5;i++)
                {
                        buf=DHT11_Read_Byte();
                }
                if((buf+buf+buf+buf)==buf)
                {
                        *humi=buf;
                        *temp=buf;
                }
        }else return 1;
        return 0;          
}
          
unsigned char BSP_DHT11_Init()
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOJ_CLK_ENABLE();
       
GPIO_Initure.Pin=GPIO_PIN_4;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOJ,&amp;GPIO_Initure);

DHT11_Rst();
        return DHT11_Check();
}</code></pre>

<p><br />
对于DHT11模块,主要评测在200MHz主频下,STM32F769采集一次DHT11温湿度数据所需要的时间间隔:</p>

<pre>
<code>
GPIOJ-&gt;BSRR |= 0x00000002;
DHT11_Read_Data(&amp;temp,&amp;humi);
GPIOJ-&gt;BSRR |= 0x00020000;
DHT11_Read_Data(&amp;temp,&amp;humi);</code></pre>

<p></p>

<p>可以看出,DHT11这种单总线且延迟较大的器件,采集一次的延时时间还是挺长的,达到了20ms,当项目要求us甚至us级实时的话,DHT11就绝对不是很好的选择。</p>

<p>然后是AD采集,这次我只做了AD常规转换的评测,没有走DMA通道,评测单次AD采集,不同采集节拍下的延时,分别是480节拍和28节拍,两组AD接口分别接了一个光敏电阻和接近传感器:</p>

<pre>
<code>ADC_HandleTypeDef hadc1,hadc3;

void BSP_ADC1_Init()
{
    hadc1.Instance=ADC1;
    hadc1.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc1.Init.Resolution=ADC_RESOLUTION_12B;
    hadc1.Init.DataAlign=ADC_DATAALIGN_RIGHT;             //右对齐
    hadc1.Init.ScanConvMode=DISABLE;                      //非扫描模式
    hadc1.Init.EOCSelection=DISABLE;                      //关闭EOC中断
    hadc1.Init.ContinuousConvMode=DISABLE;                //关闭连续转换
    hadc1.Init.NbrOfConversion=1;                         //1个转换在规则序列中 也就是只转换规则序列1
    hadc1.Init.DiscontinuousConvMode=DISABLE;             //禁止不连续采样模式
    hadc1.Init.NbrOfDiscConversion=0;                     //不连续采样通道数为0
    hadc1.Init.ExternalTrigConv=ADC_SOFTWARE_START;       //软件触发
    hadc1.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE;//使用软件触发
    hadc1.Init.DMAContinuousRequests=DISABLE;
    HAL_ADC_Init(&amp;hadc1);
}

void BSP_ADC3_Init()
{
    hadc3.Instance=ADC3;
    hadc3.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc3.Init.Resolution=ADC_RESOLUTION_12B;
    hadc3.Init.DataAlign=ADC_DATAALIGN_RIGHT;             //右对齐
    hadc3.Init.ScanConvMode=DISABLE;                      //非扫描模式
    hadc3.Init.EOCSelection=DISABLE;                      //关闭EOC中断
    hadc3.Init.ContinuousConvMode=DISABLE;                //关闭连续转换
    hadc3.Init.NbrOfConversion=1;                         //1个转换在规则序列中 也就是只转换规则序列1
    hadc3.Init.DiscontinuousConvMode=DISABLE;             //禁止不连续采样模式
    hadc3.Init.NbrOfDiscConversion=0;                     //不连续采样通道数为0
    hadc3.Init.ExternalTrigConv=ADC_SOFTWARE_START;       //软件触发
    hadc3.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE;//使用软件触发
    hadc3.Init.DMAContinuousRequests=DISABLE;
    HAL_ADC_Init(&amp;hadc3);
}

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_ADC1_CLK_ENABLE();
          __HAL_RCC_ADC3_CLK_ENABLE();
       
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOF_CLK_ENABLE();
       
    GPIO_Initure.Pin=GPIO_PIN_2;
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;
    GPIO_Initure.Pull=GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC,&amp;GPIO_Initure);
       
          GPIO_Initure.Pin=GPIO_PIN_10;
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;
    GPIO_Initure.Pull=GPIO_NOPULL;
    HAL_GPIO_Init(GPIOF,&amp;GPIO_Initure);
}

int BSP_ADC1_Get(int ch)   
{
    ADC_ChannelConfTypeDef ADC1_ChanConf;
   
    ADC1_ChanConf.Channel=ch;
    ADC1_ChanConf.Rank=1;
    ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_28CYCLES;
    ADC1_ChanConf.Offset=0;               
    HAL_ADC_ConfigChannel(&amp;hadc1,&amp;ADC1_ChanConf);
       
    HAL_ADC_Start(&amp;hadc1);
       
//    HAL_ADC_PollForConversion(&amp;hadc1,10);
   
                return (int)HAL_ADC_GetValue(&amp;hadc1);
}

int BSP_ADC3_Get(int ch)   
{
    ADC_ChannelConfTypeDef ADC3_ChanConf;
   
    ADC3_ChanConf.Channel=ch;
    ADC3_ChanConf.Rank=1;
    ADC3_ChanConf.SamplingTime=ADC_SAMPLETIME_28CYCLES;
    ADC3_ChanConf.Offset=0;               
    HAL_ADC_ConfigChannel(&amp;hadc3,&amp;ADC3_ChanConf);
       
    HAL_ADC_Start(&amp;hadc3);
       
//    HAL_ADC_PollForConversion(&amp;hadc3,10);
   
                return (int)HAL_ADC_GetValue(&amp;hadc3);
}</code></pre>

<pre>
<code>GPIOJ-&gt;BSRR |= 0x00000002;
BSP_ADC1_Get(12);
BSP_ADC3_Get(8);
DHT11_Read_Data(&amp;temp,&amp;humi);</code></pre>

<p>可以看出480节拍和28节拍的差异还是很大的,28节拍可以控制在5us左右(两次采集),480节拍则达到了20us:</p>

<p></p>

<p>最后就是RGB彩灯驱动了,这是使用了板上的PB8和PB9的一组I2C接口,走的是模拟I2C总线,给P9813传入32位灰度数据,就可以控制RGB灯三个颜色分量的变化:</p>

<p>利用触摸屏做了个演示Demo:</p>

<pre>
<code>        while (1)
{
                DHT11_Read_Data(&amp;temp,&amp;humi);
                adc_value1=BSP_ADC1_Get(12);
                adc_value2=BSP_ADC3_Get(8);
                LCD_Show_Char_1632(96,64,temp/10%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
                LCD_Show_Char_1632(112,64,temp%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);

                LCD_Show_Char_1632(96,96,humi/10%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
                LCD_Show_Char_1632(112,96,humi%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
               
                LCD_Show_Char_1632(208,128,adc_value1/1000%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
                LCD_Show_Char_1632(224,128,adc_value1/100%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
                LCD_Show_Char_1632(240,128,adc_value1/10%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
                LCD_Show_Char_1632(256,128,adc_value1%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
               
                LCD_Show_Char_1632(256,160,adc_value2/1000%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
                LCD_Show_Char_1632(272,160,adc_value2/100%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
                LCD_Show_Char_1632(288,160,adc_value2/10%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
                LCD_Show_Char_1632(304,160,adc_value2%10+'0',LCD_COLOR_BLACK,LCD_COLOR_CYAN);
               
                BSP_TS_GetState(&amp;tst);
                tx1=tst.touchX;
                ty1=tst.touchY;
                if(tx1&gt;=545)
                {
                        if(tx1&lt;565)tx1=545;
                        if(tx1&gt;780)tx1=799;
                        if(0&lt;=ty1&amp;&amp;ty1&lt;120)
                        {
                                rtemp=tx1-545;
                                BSP_LCD_FillRect(545,0,rtemp,120,LCD_COLOR_RED);
                                BSP_LCD_FillRect(tx1,0,255-rtemp,120,LCD_COLOR_CYAN);
                        }
                        else if(120&lt;=ty1&amp;&amp;ty1&lt;240)
                        {
                                gtemp=tx1-545;
                                BSP_LCD_FillRect(545,120,gtemp,120,LCD_COLOR_GREEN);
                                BSP_LCD_FillRect(tx1,120,255-gtemp,120,LCD_COLOR_CYAN);
                        }
                        else if(240&lt;=ty1&amp;&amp;ty1&lt;360)
                        {
                                btemp=tx1-545;
                                BSP_LCD_FillRect(545,240,btemp,120,LCD_COLOR_BLUE);
                                BSP_LCD_FillRect(tx1,240,255-btemp,120,LCD_COLOR_CYAN);
                        }
                        BSP_LCD_FillRect(545,360,255,120,
                        0xff000000|(rtemp&lt;&lt;16)|(gtemp&lt;&lt;8)|btemp);
                        RGB_Color_Control(rtemp,gtemp,btemp);
                }                       
        }
</code></pre>

<p></p>

<p>工程文件:</p>

<p></p>

<p>&nbsp;</p>

<p>&nbsp;</p>
页: [1]
查看完整版本: 【STM32F769Discovery开发板试用】单总线DHT11驱动&ADC光照/接近传感器&串行驱动RGB