前言
本章为智能家居项目的第二章,本章主要写51单片机的定时器timer,串口UART,中断,外接模块DHT11
同项目其他博文:
项目的概述链接:Linux智能家居项目概述-CSDN博客
第一章 主控代码开发链接:第一章 智能家居(主控)的开发及代码分析-CSDN博客
文章目录
目录
一 定时器中断
1.1 定时器0和定时器1初始化
1.2 定时器0中断函数
1.3 定时器1中断函数
二 串口波特率配置及中断115200
三 DHT11实现监测温湿度,并通过串口发送给主控系统
一 定时器中断
1.1 定时器0和定时器1初始化
C51中的定时器和计数器是同一个硬件电路支持的,通过寄存器配置不同,就可以将他当做定时器 或者计数器使用。 确切的说,定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使 用时,每经过1个机器周期,计数存储器的值就加1。而当配置为计数器时,每来一个负跳变信号 (信号从P3.4 或者P3.5引脚输入),就加1,以此达到计数的目的。 标准C51有2个定时器/计数器:T0和T1。他们的使用方法一致。C52相比C51多了一个T2
在下文的定时器函数中出现的PT0和PT1为中断优先级控制位
定时器0初始化(定时器0用于舵机控制)
void Time0Init()
{
TMOD = 0x01;
TL0=0x33; //装初值,0.5ms
TH0=0xFE;
TR0 = 1; //开始数数
TF0 = 0;
ET0 = 0; //关定时器0中断
EA = 1; //打开总中断
PT0 =1; //设定时器T0为高优先级中断
}
PT0:T0中断优先级控制位。PT0=1,设定定时器T0为高优先级中断;PT0=0,设定时器T0为低优先级中断。
定时器1初始化(定时器1 用于定时发送数据)
void Timer1Init(void) //设置定时器1
{
AUXR &= 0xBF;
TMOD &= 0x0F; //高位清0 低位不变
TMOD |= 0x10; //高位置1 低位不变
TL1 = 0x00; //装初值,定时50ms
TH1 = 0x4C;
TF1 = 0; //开始定时
TR1 = 1; //TRTF 开始数数
ET1 = 1; //打开定时器1中断
EA = 1; //打开总中断
PT1 = 0; //设定时器T1为低优先级中断
}
PT1:T1中断优先级控制位。PT1=1,设定定时器T1为高优先级中断;PT1=0,设定定时器T1为低优先级中断。
1.2 定时器0中断函数
将定时器0中断时间为0.5ms
/******************************************
*函数功能:实现舵机转现
*定时器0中断
*****************************************/
void Time0Handler() interrupt 1
{
cnt++; //用于调节IO的输出频率,用于舵机
LED_count++;
TL0=0x33; // 重装初值,设置中断时间为0.5ms
TH0=0xFE;
if(cnt < jd){ //jd = 0时舵机角度为0度,jd = 5舵机角度为180度
sg90 = 1;
}else{
sg90 = 0;
}
if(cnt == 40){
cnt = 0;
sg90 = 1;
}
}
1.3 定时器1中断函数
将定时器1中断时间为50ms
/******************************************
*函数功能:1s 发送温湿度给主机
*定时器1中断
*****************************************/
void Time1Handler() interrupt 3
{
timer1_conut++;
TL1 = 0x00; //装低八位初值 50ms
TH1 = 0x4C; //装高八位初值
if(timer1_conut == 20){ //计时一秒时,发一次温湿度数据
ET0 = 0; //定时器1断开,等待串口将温湿度数据发送完毕
timer1_conut = 0;
get_wenshidu();
ET0 = 1; //定时器1继续计时
}
}
二 串口波特率配置及中断115200
由于使用使用软件不能直接配置出115200的波特率,然后上网查资料,最后使用定时器2和波特率发生器后完成串口的配置。
//设置串口波特率为115200
void init_com( void )
{
SCON = 0x50; //串口工作方式1,8位UART,波特率可变
TH2 = 0xFF;
TL2 = 0xFD; //波特率:115200 晶振=11.0592MHz
RCAP2H = 0xFF;
RCAP2L = 0xFD; 16位自动再装入值
/*****************/
TCLK = 1;
RCLK = 1;
C_T2 = 0;
EXEN2 = 0; //波特率发生器工作方式
/*****************/
TR2 = 1 ; //定时器2开始
EA = 1; //总中断
ES = 1; //串口中断标志位
PS = 1; //设置串口优先级为最高
}
当时主控开发板的波特率为115200,然后51单片机的波特率为9600,那会我还不清楚主控的波特率是多少,就以为默认为9600,然后一通信,好家伙,数据有时对有时不对,还以为代码逻辑出了问题,改了好久好久
/* 串口中断 */
void Uart_Handler() interrupt 4{
static int i = 0; //
char tmp;
if(RI){ //收到数据RI置1
RI=0;
tmp = SBUF;
if(tmp == 'M'){
i=0;
}
cmd[i] = tmp;
i++;
if(cmd[0] == 'M'){
switch (cmd[1]){
case'1': //打开舵机中断
LED1 = OFF;
Fa_msg("开舵机中断");
//get_wenshidu();
ET0 = 1; //打开定时器0中断
break;
case'2': //关闭舵机中断
LED1 = ON;
Fa_msg("关舵机中断");
ET0 = 0; //关中断
break;
case'3':// //打开垃圾桶
Fa_msg("close ash-bin");
jd = 1;
break;
case'4': //打开垃圾桶
Fa_msg("open ash-bin");
jd = 5;
break;
case'5'://ding
Fa_msg("开始发送温湿度");
ET1 = 0;
break;
case'6'://ding
Fa_msg("停止发送温湿度");
ET1 = 1;
break;
}
}
if(i == 12){
memset(cmd,'\0',SIZE);
i = 0;
}
}
}
上述代码为串口UART中断的代码
串口没有数据时,程序正常执行,当串口接收到数据时,串口中断,程序进入串口中断函数,创建cmd[ ]数组接收数据而后判断,如果第一个数据为M时,者证明收到需要的数据,然后判断M的下一位数据cmd[1],如果判断指令存在,则执行相对应的指令
三 DHT11实现监测温湿度,并通过串口发送给主控系统
只有一根数据线DATA,51单片机发送序列指令给DHT11模块,模块一次完整的数据传输为40bit,高位先 出
51单片机发送字符串
void SendByte(char msg){//发送字节
SBUF = msg;
while(TI == 0);
TI=0;
}
void Fa_msg(char *p){//发送字符串
while(*p! = '\0'){
SendByte(*p);
p++;
}
}
将从硬件获取到的温湿度通过串口发送给主控(定时器计算每秒发送一次 )
//将获取到的温湿度值进行赋值,以便利用串口将数据发到主机
void build_data(){
shidu[0] = 'H';
shidu[1] = datas[0]/10 + 0x30;
shidu[2] = datas[0]%10 + 0x30;
shidu[3] = '.';
shidu[4] = datas[1]/10 + 0x30;
shidu[5] = datas[1]%10 + 0x30;
shidu[6] = '%';
shidu[7] = '\0';
wendu[0] = 'T';
wendu[1] = datas[2]/10 + 0x30;
wendu[2] = datas[2]%10 + 0x30;
wendu[3] = '.';
wendu[4] = datas[3]/10 + 0x30;
wendu[5] = datas[3]%10 + 0x30;
wendu[6] = 'C';
wendu[7] = '\0';
}
//将温湿度通过串口发送给主机
void get_wenshidu(){
Read_Data_Form_DHT(); //获取硬件的温度,并存进数组中
build_data();
Fa_msg(wendu); //发送温度
Fa_msg("\r\n");
//Delay1ms();
Fa_msg(shidu); //发送湿度
Fa_msg("\r\n");
}
这篇文章没用具体说明每个模块的具体实现,如需要看详解,可以看主页,或找我要笔记
推荐链接
发表评论