求各位看看,可以用红外遥控器收发信息,但只能对温度上下限改变一次,而且蜂鸣器完全不响,电脑发送9600波特率的数据也无法接收,非常疑惑
/*****************************
*****************************/
#include "reg51.h"
#include <intrins.H>
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned char u8;
typedef unsigned int u16;
char buff[2];
//LCD定义
#define LCD_DB P0
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
sbit IRED=P3^2;
//sbit K1=P3^1;
//sbit K2=P3^0;
//sbit K3=P3^2;
//sbit K4=P3^3;
bit flag=1;
extern uchar gired_data[4];
uchar gired_data[4];
sbit BEEP=P2^5;
//sbit LED=P3^4;
uchar Temp=0;
uchar H=60;
uchar L=20;
/*-------------------------------------
函数申明
---------------------------------------*/
void InitUART();
void LCD_init(void); //初始化函数
void LCD_write_command(uchar command); //写指令函数
void LCD_write_data(uchar dat); //写数据函数
void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-15),y(1-2)
void LCD_disp_str(uchar x,uchar y,uchar *str); //LCD1602显示字符串函数
void delay_n10us(uint n); //延时函数
/*----------------------------
UART1初始化
-----------------------------*/
void InitUART(void)
{
TMOD = 0x20;
SCON = 0x50;
PCON = 0x80;
TH1 = 0xF3;
TL1 = 0xF3;
EA = 1;
ES = 1;
TR1 = 1;
}
/*----------------------------
UART 中断服务程序
-----------------------------*/
void UARTInterrupt(void) interrupt 4
{
if(RI)
{
RI = 0;
buff[0]=SBUF;
Temp=buff[0];
}
else
TI = 0;
}
void ired_init(void)
{
IT0=1; //下降沿触发
EX0=1; //打开中断0允许
EA=1; //打开总中断
IRED=1; //初始化端口
}
/*-------------------------------------
LCD1602子程序
---------------------------------------*/
void LCD_init(void)
{
delay_n10us(10);
LCD_write_command(0x38);//设置8位格式,2行,5x7
delay_n10us(10); LCD_write_command(0x0c);//开显示,关光标,不闪烁
delay_n10us(10); LCD_write_command(0x06);//设定输入方式,增量不移位
delay_n10us(10); LCD_write_command(0x01);//清除屏幕显示
delay_n10us(100); //延时清屏,延时函数,延时约n个10us
}
void LCD_write_command(uchar dat)
{
delay_n10us(10);
LCD_RS=0; //指令
LCD_RW=0; //写入
LCD_E=1; //允许
LCD_DB=dat; delay_n10us(10); //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
LCD_E=0; delay_n10us(10); //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
}
void LCD_write_data(uchar dat)
{
delay_n10us(10);
LCD_RS=1; //数据
LCD_RW=0; //写入
LCD_E=1; //允许
LCD_DB=dat; delay_n10us(10);
LCD_E=0; delay_n10us(10);
}
void LCD_disp_char(uchar x,uchar y,uchar dat)
{
uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
LCD_write_data(dat);
}
void LCD_disp_str(uchar x,uchar y,uchar *str)
{
uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
while(*str!='\0')
{
LCD_write_data(*str);
str++;
}
}
void delay_n10us(uint n) //延时
{
uint i;
for(i=n;i>0;i--)
{
nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
}
//void key()
//{
// if(K1==0)
// {
// if(flag==1)
// {
// flag=0;
// if(H<128)
// {
// H++;
// }
// }
// }
// else if(K2==0)
// {
// if(flag==1)
// {
// flag=0;
// if(H>L+1)
// {
// H--;
// }
// }
// }
// else if(K3==0)
// {
// if(flag==1)
// {
// flag=0;
// if(L<H-1)
// {
// L++;
// }
// }
// }
// else if(K4==0)
// {
// if(flag==1)
// {
// flag=0;
// if(L>0)
// {
// L--;
// }
// }
// }
// else
// {
// flag=1;
// }
//}
void beep_alarm(u16 time,u16 fre)
{
while(time--)
{
BEEP=!BEEP;
delay_n10us(fre);
}
}
/*****************************
主函数
*****************************/
void main()
{
// FMQ=1;
// LED=1;
InitUART();
LCD_init();//LCD初始化
LCD_disp_str(0,1," Temp: c "); //显示 温度
LCD_disp_str(0,2,"H:000c L:000c"); //显示 湿度
ired_init();
flag = 1; // 设置计数器为1
while(1)
{
flag = 1; // 设置计数器为1
switch(gired_data[2])
{
case 0x18: //判断用户是否选择形式1
{
if(flag==1)
{
flag=0;
if(H<128)
{
H++;
}
}
break;
}
case 0x52: //判断用户是否选择形式2
{
if(flag==1)
{
flag=0;
if(H>L+1)
{
H--;
}
}
break;
}
case 0x08: //判断用户是否选择形式3
{
if(flag==1)
{
flag=0;
if(L<H-1)
{
L++;
}
}
break;
}
case 0x5A: //判断用户是否选择形式4
{
if(flag==1)
{
flag=0;
if(L>0)
{
L--;
}
}
break;
}
}
LCD_disp_char(8,1,Temp/100+'0'); //显示 温度
LCD_disp_char(9,1,Temp/10%10+'0'); //显示 温度
LCD_disp_char(10,1,Temp%10+'0'); //显示 温度
LCD_disp_char(2,2,H/100+'0');
LCD_disp_char(3,2,H/10%10+'0');
LCD_disp_char(4,2,H%10+'0');
LCD_disp_char(12,2,L/100+'0');
LCD_disp_char(13,2,L/10%10+'0');
LCD_disp_char(14,2,L%10+'0');
if(Temp<L || Temp>H)
{
beep_alarm(100,10);
}
else
{
beep_alarm(100,10);
}
}
}
void ired() interrupt 0 //外部中断0服务函数
{
u8 ired_high_time=0;
u16 time_cnt=0;
u8 i=0,j=0;
if(IRED==0)
{
time_cnt=1000;
while((!IRED)&&(time_cnt))//等待引导信号9ms低电平结束,若超过10ms强制退出
{
delay_n10us(1);//延时约10us
time_cnt--;
if(time_cnt==0)return;
}
if(IRED)//引导信号9ms低电平已过,进入4.5ms高电平
{
time_cnt=500;
while(IRED&&time_cnt)//等待引导信号4.5ms高电平结束,若超过5ms强制退出
{
delay_n10us(1);
time_cnt--;
if(time_cnt==0)return;
}
for(i=0;i<4;i++)//循环4次,读取4个字节数据
{
for(j=0;j<8;j++)//循环8次读取每位数据即一个字节
{
time_cnt=600;
while((IRED==0)&&time_cnt)//等待数据1或0前面的0.56ms结束,若超过6ms强制退出
{
delay_n10us(1);
time_cnt--;
if(time_cnt==0)return;
}
time_cnt=20;
while(IRED)//等待数据1或0后面的高电平结束,若超过2ms强制退出
{
delay_n10us(10);//约0.1ms
ired_high_time++;
if(ired_high_time>20)return;
}
gired_data[i]>>=1;//先读取的为低位,然后是高位
if(ired_high_time>=8)//如果高电平时间大于0.8ms,数据则为1,否则为0
gired_data[i]|=0x80;
ired_high_time=0;//重新清零,等待下一次计算时间
}
}
}
if(gired_data[2]!=~gired_data[3])//校验控制码与反码,错误则返回
{
for(i=0;i<4;i++)
gired_data[i]=0;
return;
}
}
}
逻辑错误比较明显 首先第一点你要了解 void UARTInterrupt(void) interrupt 4 这段函数的意思 我先指出来错误,正确应该这样写
void UARTInterrupt(void) interrupt 4
{
if(RI) //这段if语句的意思是 只要收到了数据就把数据取出来 存到BUFF里边,之后清0好为下一位数据的接收做准备
{
RI = 0;
buff[0]=SBUF;
Temp=buff[0];
}
while(!TI)//这句话意思是 如果数据没有发送完成就要一直等待
TI = 0;//发完之后清楚标志位,好继续发送
}
至于你说的按键只能调一次 这个错误很明显
case 0x5A: //判断用户是否选择形式4
{
if(flag==1)
{
flag=0;
if(L>0)
{
L--;
}
}
break;
}
当你遥控器按下时,判断的第一个if语句是判断flag是否等于1 ,如果等于1就把flag至0,但是你至0之后并没有重新至1,这就导致了按键只能调一次 正确的做法应该是在switch语句最后default之前加上flag=1;
串口通讯参数是否配置正确
建议先单独调试各个功能模块,串口,红外,蜂鸣器。
您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!