打印
[STM32F0]

STM32 NUCLEO 驱动AM2301

[复制链接]
533|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gaoyang9992006|  楼主 | 2020-8-29 22:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 gaoyang9992006 于 2020-9-16 10:18 编辑

am2301.rar (13.37 MB)
说明,使用的是NUCLEO-STM32F072RB开发板,板载一个LED,利用这个LED做一个线程,用于指示工作中。
通过PA10驱动AM2301单线协议的温湿度传感器。通过板载虚拟串口进行消息打印UART2,PA2,PA3
为了方便将所有用到的am2301相关函数都放到了am2301.h头文件里
#include "stm32f0xx_hal.h"

//读传感器 端口位定义,可修改
//*
#define AM2301_PIN  GPIO_PIN_10
#define AM2301_PORT GPIOA
#define AM2301_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOA_CLK_ENABLE()
#define AM2301_GPIO_CLK_DISABLE()    __HAL_RCC_GPIOA_CLK_DISABLE()


unsigned char Sensor_AnswerFlag;  //收到起始标志位
unsigned char Sensor_ErrorFlag;   //读取传感器错误标志
unsigned int  Sys_CNT;
unsigned char AM2301_Data[5]={0x00,0x00,0x00,0x00,0x00};

void Read_AM2301_PIN_Init(void)
{
    AM2301_GPIO_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Mode    = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull    = GPIO_PULLUP;
    GPIO_InitStruct.Speed   = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Pin     = AM2301_PIN;
    HAL_GPIO_Init(AM2301_PORT, &GPIO_InitStruct);
}

void Write_AM2301_PIN_Init(void)
{
    AM2301_GPIO_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Mode    = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull    = GPIO_PULLUP;
    GPIO_InitStruct.Speed   = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Pin     = AM2301_PIN;
    HAL_GPIO_Init(AM2301_PORT, &GPIO_InitStruct);
}

unsigned char Read_AM2301_PIN(void)
{
    return HAL_GPIO_ReadPin(AM2301_PORT, AM2301_PIN);
}

void SET_AM2301_PIN(void)
{
    HAL_GPIO_WritePin(AM2301_PORT, AM2301_PIN,GPIO_PIN_SET);
}

void RESET_AM2301_PIN(void)
{
    HAL_GPIO_WritePin(AM2301_PORT, AM2301_PIN,GPIO_PIN_RESET);
}

unsigned char Read_AM2301_Data(void)
{
    unsigned char i,cnt,buffer,tmp;
    for (i = 0; i < 8; i++)
    {
        cnt=0;
        while(!Read_AM2301_PIN())
        {
           if(++cnt>=3000)
               break;
        }
        rt_hw_us_delay(30);
        tmp=0;
        if(Read_AM2301_PIN())
            tmp=1;
        cnt=0;
        while(Read_AM2301_PIN())
        {
            if(++cnt>=2000)
                break;
        }
        buffer<<=1;
        buffer|=tmp;
    }
    return buffer;
}

unsigned char Read_Sensor(void)
{
    unsigned char i;
    Write_AM2301_PIN_Init();
    RESET_AM2301_PIN();
//    rt_thread_mdelay(2);
    HAL_Delay(2);
    SET_AM2301_PIN();
    rt_hw_us_delay(30);
    SET_AM2301_PIN();

    Read_AM2301_PIN_Init();
    Sensor_AnswerFlag=0;
    if(Read_AM2301_PIN()==GPIO_PIN_RESET)
    {
        Sensor_AnswerFlag=1;
        Sys_CNT=0;
        while(Read_AM2301_PIN()==GPIO_PIN_RESET)
        {
            if(++Sys_CNT>3000)
            {
                Sensor_ErrorFlag=1;
                return 0;
            }
        }
        Sys_CNT=0;
        while(Read_AM2301_PIN()==GPIO_PIN_SET)
        {
            if(++Sys_CNT>3000)
            {
                Sensor_ErrorFlag=1;
                return 0;
            }
        }
        for(i=0;i<5;i++)
        {
            AM2301_Data[i] = Read_AM2301_Data();
        }
    }
    else
    {
        Sensor_AnswerFlag=0;
    }
    return 1;
}


创建2个线程,一个用于LED闪烁,一个用于AM2301读取与显示。
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date           Author       Notes
* 2020-08-29     RT-Thread    first version
*/

#include <rtthread.h>
#include <rthw.h>
#include <am2301.h>

//配置优先级,栈大小,时间片,设置不对没法运行的。
#define THREAD_PRIORITY         5
#define THREAD_STACK_SIZE       512
#define THREAD_TIMESLICE        5

//LED配置
#define LED_PIN  GPIO_PIN_5
#define LED_PORT GPIOA
#define LED_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOA_CLK_ENABLE()
#define LED_GPIO_CLK_DISABLE()    __HAL_RCC_GPIOA_CLK_DISABLE()
#define LED_ON()        HAL_GPIO_WritePin(LED_PORT, LED_PIN,GPIO_PIN_SET);
#define LED_OFF()        HAL_GPIO_WritePin(LED_PORT, LED_PIN,GPIO_PIN_RESET);
void led(void *parameter)
{
    LED_GPIO_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Mode    = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull    = GPIO_PULLUP;
    GPIO_InitStruct.Speed   = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Pin     = LED_PIN;
    HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);

    while(1)
    {
        rt_kprintf("LED=============================================\n");
        LED_ON();
        rt_kprintf("LED is ON\n");
        rt_thread_mdelay(2500);
        LED_OFF();
        rt_kprintf("LED is OFF\n");
        rt_thread_mdelay(2500);
    }
}

MSH_CMD_EXPORT(led, RT-led sample);


void am2301(void *parameter)
{
    unsigned char i=0;
    int wendu,shidu;
    rt_kprintf("\n");
    while(1)
    {
        rt_kprintf("AM2301=============================================\n");
        rt_thread_mdelay(10000);
        Read_Sensor();
        for(i=0;i<5;i++)
            rt_kprintf("AM2301_Data[%d]=%d\n",i,AM2301_Data[i]);

        if(AM2301_Data[4]==(AM2301_Data[0]+AM2301_Data[1]+AM2301_Data[2]+AM2301_Data[3])) rt_kprintf("Check is OK\n");
        shidu=AM2301_Data[0];
        shidu<<=8;
        shidu=shidu|AM2301_Data[1];
        wendu=AM2301_Data[2];
        wendu<<=8;
        wendu=wendu|AM2301_Data[3];
        rt_kprintf("shidu=%d.%d\%\n",shidu/10,shidu%10);
        rt_kprintf("wendu=%d.%dC\n",wendu/10,wendu%10);
        for(i=0;i<5;i++)
            AM2301_Data[i]=0;
    }

}
MSH_CMD_EXPORT(am2301, RT-am2301 sample);
int myapp(void)
{
    static rt_thread_t tid1 = RT_NULL;
    static rt_thread_t tid2 = RT_NULL;
        /* 创建线程1 */
        tid1 = rt_thread_create("thread1",
                                am2301, RT_NULL,
                                THREAD_STACK_SIZE,
                                THREAD_PRIORITY, THREAD_TIMESLICE);
        if (tid1 != RT_NULL)
            rt_thread_startup(tid1);

        tid2 = rt_thread_create("thread2",
                                led, RT_NULL,
                                THREAD_STACK_SIZE,
                                THREAD_PRIORITY-1, THREAD_TIMESLICE);
        if (tid2 != RT_NULL)
            rt_thread_startup(tid2);

    return 0;
}
MSH_CMD_EXPORT(myapp, RT-Thread sample);


int main(void)
{
    rt_kprintf("Hello\n");
    rt_thread_mdelay(1000);
    myapp();
    return RT_EOK;
}



使用特权

评论回复
沙发
gaoyang9992006|  楼主 | 2020-8-29 22:53 | 只看该作者

这么凌乱的显示顺序,说明一个问题两个线程是互相不影响的,不会傻傻的只让一个线程霸占了CPU,也就是通过RTOS实现了分时复用CPU。
这就是RTOS的好处,如果你用于按键操作,同时要扫描显示到数码管,你会发现RTOS是你明智的选择。这样按键傻傻等待的时候不会导致显示中断

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1971

主题

15978

帖子

210

粉丝