uC/OS室温计

Posted tommybjia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uC/OS室温计相关的知识,希望对你有一定的参考价值。

一、           实验目的和要求

1.     学习Uc/OS II的应用程序编写;

2.     理解如何直接操作GPIO,体会与Linux的不同;

3.     学习单总线设备的访问方式;

4.     学习7段数码管的实时复用驱动方式。

 

二、           实验器材

1.     STM32F103核心板一块;

2.     MicroUSB线一根;

3.     面包板一块;

4.     两位7段数码管(共阳)一颗;

5.     360ou 1/8W电阻2颗;

6.     DHT-11温湿度传感器1个;

7.     面包线若干;

8.     编译软件;

9.     Fritzing

 

三、           实验内容和原理

1.设计输出方案,画连线示意图;

2.在面包板上连线,完成外部电路;

3.编写C/C++程序,测试程序和电路;

a)       测试、实现uC/OS对GPIO的访问;

b)       实现DHT-11数据的读

c)       实现以时分复用方式在四位7段数码管上一次现实0000-9999数字

d)       用两个uC/OS II人物,一个定时读DHT-11数据,一个轮流驱动数码管,一秒一次显示当前温度和湿度。注意处理好两个任务之间的数据共享。

 

四、           实验过程和数据记录

1.     首先使用Fritzing画出面包板示意图,示意图如下:


2.     然后在面包板上连线,连线图如下:


 

3.     下面使用C/C++编写程序

a.      测试、实现uC/OS对GPIO的访问;

配置相关GPIO端口,使用A11-12,C14-15作为7端数码管的选择位,使用A0-7作为7端数码管各led的显示。

void GPIO_Configuration(void)

    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_DeInit();

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOA, ENABLE);

    //C14-15初始化

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14

                                | GPIO_Pin_15;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOC, &GPIO_InitStructure);

    //A0-7,11-12初始化

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin0-7...11-12;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

 

b.     实现DHT-11数据的读

uint8_t DHT11_Check()

    return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8);

 

void DHT11_Wait(int state)

    while (DHT11_Check() != state);

 

void DHT11_Rst()

    //请求数据协议

    DHT11_Pin_OUT();

    DHT11_Set(0);

    Delay_us(25000);

    DHT11_Set(1);

    Delay_us(30);

    DHT11_Set(0);

    DHT11_Pin_IN();

//5次读取中每次读取的数据

uint8_t DHT11_Read_Byte()

    int i, cnt;

    uint8_t data = 0;

    for (i=0; i<8; i++)

        cnt = 0;

        data <<= 1;

        DHT11_Wait(1);

        while (DHT11_Check() > 0)

            Delay_us(1);

            cnt++;

       

        data |= cnt > 5;

   

    return data;

//读取一次完整数据到buf

uint8_t DHT11_Read_Data(uint8_t *buf)

    int i;

    int cpu_sr;

    //DHT11对数据交换时时间要求高,故需要关闭中断以防协议中断。

    OS_ENTER_CRITICAL();

    DHT11_Rst();

    if (DHT11_Check() == 0)

        DHT11_Wait(1);

        DHT11_Wait(0);

        for (i=0; i<5; i++)

            buf[i] = DHT11_Read_Byte();

       

        DHT11_Pin_OUT();

        OS_EXIT_CRITICAL();

        // 读取的第五个数据为校验数据

        if (buf[0] + buf[1] + buf[2] + buf[3] == buf[4])

            return 1;

        else

            return 0;

       

    else

        OS_EXIT_CRITICAL();

           return 0;

   

 

 

c.      实现以时分复用方式在四位7段数码管上一次现实0000-9999数字

 

由于有共阳极的特性,七段数码管需要使用时分复用的方式进行显示数据。

//选择显示数据位,4位输出数据只有一个置位,其为选择显示的位

void digit_select(int index)

    BitAction v[4];

    int i;

    for (i=0; i<4; i++)

        //根据index选择显示位

        if (index == i)

            v[i] = Bit_SET;

        else

            v[i] = Bit_RESET;

       

   

    GPIO_WriteBit(GPIOA, GPIO_Pin_11, v[0]);

    GPIO_WriteBit(GPIOA, GPIO_Pin_12, v[1]);

    GPIO_WriteBit(GPIOC, GPIO_Pin_14, v[2]);

    GPIO_WriteBit(GPIOC, GPIO_Pin_15, v[3]);

//根据输入数字点亮对应led,共8位,包括小数点以及7段数码管

void digit_show(int digit)

    int segment, i, base;

    BitAction v[8];

    switch (digit)

        case    0    :    segment = 0xc0; break;

        case    1    :    segment = 0xf9; break;

        case    2    :    segment = 0xa4; break;

        case    3    :    segment = 0xb0; break;

        case    4    :    segment = 0x99; break;

        case    5    :    segment = 0x92; break;

        case    6    :    segment = 0x82; break;

        case    7    :    segment = 0xf8; break;

        case    8    :    segment = 0x80; break;

        case    9    :    segment = 0x90; break;

        default      :    segment = 0x86; break;

   

    base = 1 << 8;

    // 由于数码管为共阳极,所以此处置位为不显示。

    for (i=0; i<8; i++)

        base >>= 1;

        if ((segment & base )== 0)

            v[i] = Bit_RESET;

        else

            v[i] = Bit_SET;

       

   

    GPIO_WriteBit(GPIOA, GPIO_Pin_0, v[0]);

    GPIO_WriteBit(GPIOA, GPIO_Pin_1, v[7]);

    GPIO_WriteBit(GPIOA, GPIO_Pin_2, v[6]);

    GPIO_WriteBit(GPIOA, GPIO_Pin_3, v[5]);

    GPIO_WriteBit(GPIOA, GPIO_Pin_4, v[4]);

    GPIO_WriteBit(GPIOA, GPIO_Pin_5, v[3]);

    GPIO_WriteBit(GPIOA, GPIO_Pin_6, v[2]);

    GPIO_WriteBit(GPIOA, GPIO_Pin_7, v[1]);

//控制时分复用,每调用一次显示对应的一位,使用静态变量控制选择位

void display(int digit)

    static int index = -1;

    int i;

    int base = 1000;

    index = (index + 1) % 4;

    //index=0-3时分别对应从左到右四位

    for (i=0; i<index; i++)

        base /= 10;

   

    digit = (digit / base) % 10;

    digit_select(index);

    digit_show(digit);

 

 

显示0000-9999的功能调用display函数。由于其需要显示一段时间才能显示完整的四位数字,所以需要循环一段时间。

void ShowData(void* pdata)

        int value, i;

        for (value = 0; value < 10000 ;value += 1111)

            for (i = 0; i < 200; i++)

                display(value);

                Delay_ms(5);

           

            if (value == 9999)

                value = 0;

       

 

下图是显示效果


 

d.     用两个uC/OS II人物,一个定时读DHT-11数据,一个轮流驱动数码管,一秒一次显示当前温度和湿度。注意处理好两个任务之间的数据共享。

 

void GetData(void* pdata)

    uint8_t buf[5];

    memset(buf, 0, sizeof(buf));

    while (1)

       //检验数据有效性

        if(DHT11_Read_Data(buf) == 1)

       

            //温度+湿度

            ledValue = buf[2]*100 + buf[0];

       

       

        Delay_ms(1000);

   

 

void ShowData(void* pdata)

     while(1)

    

         //由于传感器数据读取有1s间隔,数值能够稳定显示。

         display(ledValue);

         Delay_ms(5);

    

 

 

在main函数前面,创建两个优先级为1和2的任务,由于读取数据的任务更重要,所以优先级更高。

int GetData_Task_STK[STK_Size];

int ShowData_Task_STK[STK_Size];

int main()

    GPIO_Configuration();

    OSInit();

    OS_CPU_SysTickInit();

    OSTaskCreate(

        GetData,

        (void *)0,

        (OS_STK *)&GetData_Task_STK[STK_Size-1],

        1);

    OSTaskCreate(

        ShowData,

        (void *)0,

        (OS_STK *)&ShowData_Task_STK[STK_Size-1],

        2

    );

    OSStart();

    return 0;

 

                     下图为显示效果:


表明现在温度是26摄氏度,湿度为54%


以上是关于uC/OS室温计的主要内容,如果未能解决你的问题,请参考以下文章

uC/OS室温计

uC/OS室温计

华脉恒温恒湿如何

uC/OS-III-11.0-uC/OS-III软件定时器

uC/OS-III-11.1-uC/OS-III软件定时器

ucos-III前言