#5 uC/OS室温计
这个实验的目的是理解uC/OS II的任务调度方式,编写uC/OS II的应用程序,通过寄存器直接操纵GPIO来驱动外 部设备。
##配合课程
RTOS
##实验目的
学习uC/OS II的应用程序编写;
理解如何直接操纵GPIO,体会与Linux的不同;
学习单总线设备的访问方式;
学习7段数码管的时分复用驱动方式。
##实验器材
###硬件
STM32F103板一块;
USB串口板一块;
面包板一块;
两位7段数码管(共阳)一颗;
360Ω 1/8W电阻2颗;
DHT-11 温湿度传感器1个;
面包线若干。
###软件
####编译软件;
Fritzing。
uvison5.
#实验步骤
设计输出方案,画连线示意图;
在面包板上连线,完成外部电路;
编写C/C++程序,测试程序和电路;
- 测试、实现uC/OS II对GPIO的访问;
- 实现DHT-11数据的读;
- 实现以时分复用方式在四位7段数码管上依次显示0000-9999的数字;
- 用两个uc/OS II任务,一个定时读DHT-11数据,一个轮流驱动数码管,一秒一次显示当前温度和湿度。注意处理好 两个任务之间的数据共享。
#连线示意图
以上为四位共阳数码管的引脚图片
以上为四位共阳数码管的接线图片,由于在fritzing中没有找到合适的stm32板子,所以将这块25pin的引脚除去下面的6个pin就当它做STM32F103了,在实体连线中,将数码管COM1-4分别连接到了C15-14,A0-A1,其余脚按照顺时针顺序连接到了STM32板的两端。
如图为dht的连线图,在本次试验中,Vcc接3.3V,Dout接A8,GND接地,为了读数稳定,需要在地线和Dout间连接一个上拉电阻。
#实验过程
###UCOS的移植
在UCOS移植的过程中参考了网上的资料。
IDE环境:uvision5, UCOS源码。
文章来源sina blog
1 | 1.新建ucos工程,选择STM32F103VE,选择CMSIS下的CORE和Device下的Startup,以及Device下的StdPeriph Drivers下的Framework,RCC,和GPIO |
在app.c中还需要添加如下时钟中断处理函数:
1 | void SysTick_handler(void){ |
这样全部做完之后代码结构如图:
###GPIO的访问
首先,在GPIO初始化函数中,初始化所有我们需要的GPIO,当然这里是全部要用到的都初始化了。
1 | void GPIO_Configuration(void) { |
随便点个小灯来测试一下吧(其实是做完后面的反过来做得这个):
1 | GPIO_WriteBit(GPIO_C,GPIO_Pin_14,RESET); |
###时分复用的八位共阳数码管
首先为了在单独的一位数字上显示出我们想要的数字,要根据数码管每一位所对应的引脚输入正确的值。
1 | unsigned char table[10][8] = |
以上的代码分别对应了0-9的数字在数码管上的显示IO管脚电平,按照顺时针方向,从8字顶端开始为ABCDEFG,DP,而代码中从高到低对应DP,GFEDCBA。这样就可以在数码管上显示单个数字了,为了保险起见,可以给数码管接个电阻避免烧坏。
为了同时点亮四个数字,利用人眼的余晖效应,只要快速切换点亮每个数字,在人眼看来就像是同时亮起来的一样。这时就需要时分复用技术了。对于共阳数码管,每个数字当我们想让他亮的时候,将对应的阳极置为高电平即可,如下为选择数码管位数的函数。
1 | void digit_choose(int index){ |
再在主程序中编写时分复用的代码:
1 | void display(int digit){ |
这样就可以在数码管上显示数字0-9999了。
###DHT11温湿计使用
DHT11是一种单总线的传感器,这意味着它的输入和输出引脚是公用的。这样就需要以精确的时间给它发送信号,它的开启模式是这样的:
1 | 总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证 |
DHT11的响应信号为将电平拉高,通常拉高80μs后就会开始传输数据。数据格式如下:
1 | 数据格式:8bit湿度整数数据 |
这样就可以在GPIO A8口读到DHT11送来的数据了。
在程序中我们需要编写将DHT11激活的函数:
1 | void DHT11_Set(int state){//设置数据读取引脚电平 |
激活后再按照传入的数据格式编写一下读取数据的函数即可读取DHT11传来的数据了。
1 | uint8_t DHT11_Read_Byte(){ |
至此已经可以读取DHT11的数据了。
###双任务执行
使用UCOS来执行两个任务其实非常方便,只需要使用UCOS开启两个进程即可。
1 | void gainData(void * data) |
运行结果为: