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室温计的主要内容,如果未能解决你的问题,请参考以下文章