资讯详情

实时时钟+红外+温度传感器+LCD1602显示

此程序是在51hei单片机上面做的,如需要移植到自己的电路上,修改相应的端口即可,开发板完整的电路图下载: 点这里(注意:只需要看相关部分的连线如液晶屏 等和单片机的连接方式,其他部分可以忽略)

/** **************************************************************************** * @file main.c * @author xr * @date 2014年4月10日22:21:56 * @version V1.2.3 * @brief 在1602上显示时钟,当前温度值,和NEC协议的红外解码值 * @note 单片机C89C52RC 晶振 11.0592MHZ **************************************************************************** */

#include <reg52.h> #include "mytype.h" bit fack = 0;//接收到温度数据标志位 bit flag1s = 0;//1s时间标志位 bit flag200ms = 0;//200ms标志 uint8 thr0, tlr0; uint8 counter = 0, i = 0; // 编码 uint8 code LedTable[] = { 0xC0, //"0" 0xF9, //"1" 0xA4, //"2" 0xB0, //"3" 0x99, //"4" 0x92, //"5" 0x82, //"6" 0xF8, //"7" 0x80, //"8" 0x90, //"9" 0x88, //"A" 0x83, //"B" 0xC6, //"C" 0xA1, //"D" 0x86, //"E" 0x8E //"F" }; extern void InitLcd1602(); extern void LcdShowStr(uint8 x, uint8 y, uint8 * str); extern bit StartDs18B20(); extern bit ReadDs18B20Temp(int * temp); extern void InitDS1302(); extern void DS1302BurstRead(uint8 * time); extern void InitInfrared(); //外部变量只是声明,不可以重新赋值 extern bit Irflag;//红外遥控器解码数据接收完成标志 extern uint8 Ircode[4];//存放遥控器解码值(用户码, 用户码反码,键码,键码反码) void ConfigTimer0(uint16 xms); uint8 IntToString(uint8 * str, int dat); void main(void) { uint8 buf[4]; uint8 len = 0; int temp;//温度 int intT, decT;//整数部分,小数部分 uint8 str[20]; uint8 time[20];//保存时间(BCD码值) uint8 psec = 0xFF;//sec最大是59,所以一定能刷新显示 InitLcd1602(); InitDS1302(); ConfigTimer0(10);//定时10ms StartDs18B20(); InitInfrared(); while (1) { if (Irflag) //红外解码 { Irflag = 0; buf[0] = Ircode[2] / 10 % 10;//按键码的十位数 buf[1] = Ircode[2] % 10;//按键码的个位数 str[0] = buf[0] + '0'; str[1] = buf[1] + '0'; str[2] = '\0'; LcdShowStr(14, 1, str); } if (flag200ms) //200ms刷新时钟显示 { flag200ms = 0; DS1302BurstRead(time); if (psec != time[0]) //time[0]保存的是sec寄存器的BCD码值 { //刷新显示 //日期 str[0] = '2'; str[1] = '0'; str[2] = (time[6] >> 4) + '0';//取年十位 str[3] = (time[6] & 0x0F) + '0';//取年个位转字符 str[4] = '-'; str[5] = (time[4] >> 4) + '0'; //月十位 str[6] = (time[4] & 0x0F) + '0'; //月个位 str[7] = '-'; str[8] = (time[3] >> 4) + '0'; //日十位 str[9] = (time[3] & 0x0F) + '0'; //日个位 str[10] = '\0'; LcdShowStr(0, 0, str); //时间 str[0] = (time[2] >> 4) + '0';//时十位 str[1] = (time[2] & 0x0F) + '0';//时个位 str[2] = ':'; str[3] = (time[1] >> 4) + '0'; str[4] = (time[1] & 0x0F) + '0'; str[5] = ':'; str[6] = (time[0] >> 4) + '0'; str[7] = (time[0] & 0x0F) + '0'; str[8] = '\0'; LcdShowStr(0, 1, str); //星期 str[0] = (time[5] & 0x0F) + '0';//星期只有一位数字 str[1] = '\0'; LcdShowStr(11, 0, "Week"); LcdShowStr(15, 0, str); psec = time[0]; } } if (flag1s) //1s刷新温度显示 { flag1s = 0; fack = ReadDs18B20Temp(&temp);//读取温度 if (fack) //读取成功 { intT = (temp >> 4);//整数部分,将小数部分移出 decT = (temp & 0x000F);//小数部分 len = IntToString(str, intT);//将intT整数部分转换成字符存入str中,并返回有效字符个数 str[len++] = '.';//小数点 decT = decT * 10 / 16 % 10;//小数部分转换 str[len++] = decT + '0'; str[len] = '\0'; LcdShowStr(8, 1, "T:"); LcdShowStr(10, 1, str); } else { LcdShowStr(0, 0, "error!"); } } StartDs18B20();//重新启动温度转换 } } //定时器T0配置 void ConfigTimer0(uint16 xms) { uint16 tmp; tmp = 65536-xms*11059200/12/1000; thr0 = (uint8)(tmp >> 8);//取高字节 tlr0 = (uint8)(tmp & 0x00FF);//取低字节 TMOD &= 0xF0;//清零T0控制位 TMOD |= 0x01;//T0方式1 TH0 = thr0; TL0 = tlr0;//装入定时初值 TR0 = 1;//启动T0定时器 EA = 1;//开总中断 ET0 = 1;//开定时器T0中断 //PT0 = 1;//设置T0中断优先级为最高级 } //整数转换成str unsigned char IntToString(unsigned char * str, signed int dat) { unsigned char len = 0;//统计有效字符的个数 signed char i = 0;// unsigned char buff[6];//数据分解缓冲区 if (dat < 0) //负数 { dat = -dat;//取绝对值 *str++ = '-';//前面加上- len++;//长度++ } //分解整数dat到buff中 do { buff[i++] = dat % 10; dat /= 10; } while (dat > 0);//分解到dat==0为止 len += i;//长度+i,有效字符个数 while (i-- > 0) //拷贝转换后的ASIIC码字符到str接收指针中 { *str++ = buff[i] + '0';//转换成ASCII字符 } *str = '\0';//加上串结束符 return len;//返回有效字符个数 } //定时器T0中断服务 void timer0_I () interrupt 1 { TH0 = thr0; TL0 = tlr0; counter++; if (counter >= 20) { counter = 0; flag200ms = 1; i++; if (i >= 5) { i = 0; flag1s = 1; } } } /**********自定义头文件************/ #ifndef _MYTYPE_H_H #define _MYTYPE_H_H typedef unsigned int uint16; typedef unsigned char uint8; typedef unsigned long uint32; #endif //_MYTYPE_H_H /***************LCD1602.c*********************/ #include <reg52.h> #include "mytype.h" //LCD1602 sbit LCD1602_RS = P1^0; sbit LCD1602_RW = P1^1; sbit LCD1602_EN = P1^5; #define LCD1602_ P0 //液晶忙碌等待 void WaitLcd1602() { uint8 sta; LCD1602_DB = 0xFF;//拉高P0口 LCD1602_RS = 0; LCD1602_RW = 1; do { LCD1602_EN = 1; sta = LCD1602_DB; LCD1602_EN = 0;//关闭液晶的数据输出 } while (sta & 0x80); } //写命令 void WriteLcd1602Cmd(uint8 cmd) { WaitLcd1602(); LCD1602_RS = 0; LCD1602_RW = 0; LCD1602_DB = cmd; LCD1602_EN = 1;//高脉冲 LCD1602_EN = 0; } //写数据 void WriteLcd1602Data(uint8 dat) { WaitLcd1602(); LCD1602_RS = 1; LCD1602_RW = 0; LCD1602_DB = dat; LCD1602_EN = 1;//高脉冲 LCD1602_EN = 0; } //液晶初始化 void InitLcd1602() { WriteLcd1602Cmd(0x38);//设置16*2显示 5*7点阵 8位数据口 WriteLcd1602Cmd(0x0C);//开显示不显示光标 WriteLcd1602Cmd(0x06);//写入一个字符时字符指针++且地址++ WriteLcd1602Cmd(0x01);//清屏 } //写str到LCD1602 void LcdShowStr(uint8 x, uint8 y, uint8 * str) { uint8 addr; if (y == 0) { //第一行 addr = 0x00 + x; } else { //第二行 addr = 0x40 + x; } WriteLcd1602Cmd(0x80 | addr); while (*str != '\0') { WriteLcd1602Data(*str++); } } /** ********************************************************************* * @file infrared.c * @author xr * @date 2014年4月11日08:25:04 * @version V1.2.3 * @brief 红外通信-NEC协议红外遥控器解码驱动 * @note 单片机STC89C52RC MCU 晶振 11.0592MHZ ********************************************************************* */ #include <reg52.h> #include "mytype.h" //红外通信位声明 sbit D = P3^3; bit Irflag = 0;//红外遥控器解码数据接收完成标志 uint8 Ircode[4];//存放遥控器解码值(用户码, 用户码反码,键码,键
锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台