万年历单片机C语言报告,51单片机万年历C语言

该程序展示了如何使用单片机进行DS1820温度传感器的数据读取,并将结果显示在LCD显示器上。同时实现了按键扫描功能,用于与用户交互,当检测到特定按键时,会触发蜂鸣器响应。程序中包含了延时函数、LCD初始化、数据传输和温度转换等关键操作。
摘要由CSDN通过智能技术生成

#include

#include

#define uchar unsigned char

#define uint  unsigned int

uchar buf1;

uchar buf2;

uchar buf3;

uchar  tt;

uchar  n=0;                //键顺序吗

uchar  dis_buf;            //显示缓存

uchar  temp;

uchar  key;

uchar  enter;

void delay0(uchar x);      //x*0.14MS

sbit LCD_RW = P2^5;

sbit LCD_RS = P2^6;

sbit LCD_EN = P2^7;

sbit DQ=P3^7;

sbit RQ=P1^5;

uchar data disdata[5];

uint tvalue;//温度值

uchar tflag;//温度正负标志

uchar cdis1[16] = {"T:      C "};

uchar cdis2[16] = {"H:    C L:   C "};

uchar  cdis3[16];

#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

/*************************************************************/

/*                                                           */

/* 延时子程序*/

/*                                                           */

/*************************************************************/

void  delay(uchar x)

{ uchar j;

while((x--)!=0)

{ for(j=0;j<125;j++)

{;}

}

}

/*************************************************************/

/*                                                           */

/*检查LCD忙状态*/

/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据*/

/*                                                           */

/*************************************************************/

bit lcd_busy()

{

bit result;

LCD_RS = 0;

LCD_RW = 1;

LCD_EN = 1;

delayNOP();

result = (bit)(P0&0x80);

LCD_EN = 0;

return(result);

}

/*******************************************************************/

/*                                                                 */

/*写指令数据到LCD                                                  */

/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。*/

/*                                                                 */

/*******************************************************************/

void lcd_wcmd(uchar cmd)

{

while(lcd_busy());

LCD_RS = 0;

LCD_RW = 0;

LCD_EN = 0;

_nop_();

_nop_();

P0 = cmd;

delayNOP();

LCD_EN = 1;

delayNOP();

LCD_EN = 0;

}

/*******************************************************************/

/*                                                                 */

/*写显示数据到LCD                                                  */

/*RS=H,RW=L,E=高脉冲,D0-D7=数据。*/

/*                                                                 */

/*******************************************************************/

void lcd_wdat(uchar dat)

{

while(lcd_busy());

LCD_RS = 1;

LCD_RW = 0;

LCD_EN = 0;

P0 = dat;

delayNOP();

LCD_EN = 1;

delayNOP();

LCD_EN = 0;

}

/*************************************************************/

/*                                                           */

/*  LCD初始化设定*/

/*                                                           */

/*************************************************************/

void lcd_init()

{

delay(15);

lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据

delay(5);

lcd_wcmd(0x38);

delay(5);

lcd_wcmd(0x38);

delay(5);

lcd_wcmd(0x0C);      //显示开,关光标

delay(5);

lcd_wcmd(0x06);      //移动光标

delay(5);

lcd_wcmd(0x01);      //清除LCD的显示内容

delay(5);

}

/*************************************************************/

/*                                                           */

/*  设定显示位置*/

/*                                                           */

/*************************************************************/

void lcd_pos(uchar pos)

{

lcd_wcmd(pos | 0x80);  //数据指针=80+地址变量

}

/*************************************************************/

/*                                                           */

/* 键扫描子程序(4*3的矩阵) P1.4 P1.5 P1.6 P1.7为行*/

/*                                                          P1.1 P1.2 P1.3为列*/

/*                                                                                             */

/*************************************************************/

void  keyscan(void)

{

P1=0xF0;                 //高四位输入   行为高电平  列为低电平

delay(1);

temp=P1;                 //读P1口

temp=temp&0xF0;                         //屏蔽低四位

temp=~((temp>>4)|0xF0);

if(temp==1)          // p1.4 被拉低

key=0;

else if(temp==2)   // p1.5 被拉低

key=1;

else if(temp==4)   // p1.6 被拉低

key=2;

else if(temp==8)

key=0;

P1=0x0F;                //低四位输入  列为高电平 行为低电平

delay(1);

temp=P1;                //读P1口

temp=temp&0x0F;

temp=~(temp|0xF0);

if(temp==1)                   // p1.1  被拉低

key=key+0;

else if(temp==2)   // p1.2  被拉低

key=key+2;

else if(temp==4)        // p1.3  被拉低

key=key+4;

else if(temp==8)

key=key+8;

dis_buf = key;                     //键值入显示缓存

if(dis_buf>9)               //转换为ASCII码

dis_buf = dis_buf+0x37;

else

dis_buf = dis_buf+0x30;

}

/*************************************************************/

/*                                                           */

/*判断键是否按下*/

/*                                                           */

/*************************************************************/

void  keydown(void)

{

P1=0xF0;

if(P1!=0xF0)  //判断按键是否按下 如果按钮按下 会拉低P1其中的一个端口

{

delay(10);

if(P1!=0xF0)

{

keyscan();

P1=0xF0;

while(P1!=0xF0);

if(dis_buf=='A')

enter=1;

if(enter==0)

{

if(n==4)

n=0;

if(dis_buf!='B')

{

cdis3[n]=dis_buf;

n++;

}

}

if(dis_buf=='B')

enter=0;

}

}

}

/******************************ds1820程序***************************************/

void delay_18B20(unsigned int i)//延时1微秒

{

while(i--);

}

void ds1820rst()/*ds1820复位*/

{ unsigned char x=0;

DQ = 1;          //DQ复位

delay_18B20(4); //延时

DQ = 0;          //DQ拉低

delay_18B20(100); //精确延时大于480us

DQ = 1;          //拉高

delay_18B20(40);

}

uchar ds1820rd()/*读数据*/

{ unsigned char i=0;

unsigned char dat = 0;

for (i=8;i>0;i--)

{   DQ = 0; //给脉冲信号

dat>>=1;

DQ = 1; //给脉冲信号

if(DQ)

dat|=0x80;

delay_18B20(10);

}

return(dat);

}

void ds1820wr(uchar wdata)/*写数据*/

{unsigned char i=0;

for (i=8; i>0; i--)

{ DQ = 0;

DQ = wdata&0x01;

delay_18B20(10);

DQ = 1;

wdata>>=1;

}

}

read_temp()/*读取温度值并转换*/

{uchar a,b;

ds1820rst();

ds1820wr(0xcc);//*跳过读序列号*/

ds1820wr(0x44);//*启动温度转换*/

ds1820rst();

ds1820wr(0xcc);//*跳过读序列号*/

ds1820wr(0xbe);//*读取温度*/

a=ds1820rd();

b=ds1820rd();

tvalue=b;

tvalue<<=8;

tvalue=tvalue|a;

if(tvalue<0x0fff)

tflag=0;

else

{tvalue=~tvalue+1;

tflag=1;

}

tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数

return(tvalue);

}

/*******************************************************************/

void ds1820disp()//温度值显示

{ uchar flagdat;

disdata[0]=tvalue/1000+0x30;//百位数

disdata[1]=tvalue%1000/100+0x30;//十位数

disdata[2]=tvalue%100/10+0x30;//个位数

disdata[3]=tvalue%10+0x30;//小数位

if(tflag==0)

flagdat=0x20;//正温度不显示符号

else

flagdat=0x2d;//负温度显示负号:-

if(disdata[0]==0x30)

{disdata[0]=0x20;//如果百位为0,不显示

if(disdata[1]==0x30)

{disdata[1]=0x20;//如果百位为0,十位为0也不显示

}

}

lcd_pos(5);

lcd_wdat(flagdat);//显示符号位

lcd_pos(6);

lcd_wdat(disdata[1]);//显示十位

lcd_pos(7);

lcd_wdat(disdata[2]);//显示个位

lcd_pos(8);

lcd_wdat(0x2e);//显示小数点

lcd_pos(9);

lcd_wdat(disdata[3]);//显示小数位

}

/*************蜂鸣器*********************************/

void fengming1(uchar tt)

{   if(tt!=1)

{

tt--;

RQ=1;

delay(100);

RQ=0;

delay(100);

}

}

void fengming2(uchar tt)

{  if(tt!=1)

{

tt--;

RQ=1;

delay(1000);

RQ=0;

delay(1000);

}

}

/*************************************************************/

/*                                                           */

/* 主程序*/

/*                                                           */

/*************************************************************/

main()

{

uchar m;

enter=0;

P0=0xFF;                    //置P0口

P1=0xFF;                    //置P1口

delay(10);                 //延时

lcd_init();                //初始化LCD

lcd_pos(0);                //设置显示位置为第一行的第1个字符

m = 0;

while(cdis1[m] != '\0')

{                         //显示字符

lcd_wdat(cdis1[m]);

m++;

}

lcd_pos(0x40);             //设置显示位置为第二行第1个字符

m = 0;

while(cdis2[m] != '\0')

{

lcd_wdat(cdis2[m]);      //显示字符

m++;

}

dis_buf = 0x2d;         //显示字符"-"

while(1)

{

read_temp();//读取温度

ds1820disp();//显示

keydown();

lcd_pos(0x43);

for(m=0;m<2;m++)

{

lcd_wdat(cdis3[m]);

}

lcd_pos(0x4d);

for(m=2;m<4;m++)

{

lcd_wdat(cdis3[m]);

}

if(enter==1)

{

buf1=cdis3[0]*10+cdis3[1];

buf2=cdis3[2]*10+cdis3[3];

buf3=disdata[1]*10+disdata[2];

if(buf1 < buf3)

{fengming1(100); }

if(buf2 > buf3)

{fengming2(100); }

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于C51单片机万年历程序示例: ```c #include <reg52.h> // 定义闰年月份天数 unsigned char code day_table[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; unsigned char code day_leap_table[12] = {31,29,31,30,31,30,31,31,30,31,30,31}; // 定义LCD1602连接引脚 sbit RS=P2^0; sbit RW=P2^1; sbit EN=P2^2; sbit LCD1602_DATAPINS_4=P0^4; sbit LCD1602_DATAPINS_5=P0^5; sbit LCD1602_DATAPINS_6=P0^6; sbit LCD1602_DATAPINS_7=P0^7; // 函数声明 void init_lcd(void); // 初始化LCD1602 void display_char(unsigned char x,unsigned char y,unsigned char dat); // 在LCD1602指定位置显示一个字符 void display_string(unsigned char x,unsigned char y,unsigned char *s); // 在LCD1602指定位置显示一个字符串 void display_date(unsigned char year,unsigned char month,unsigned char day); // 在LCD1602指定位置显示日期 // 主函数 void main() { unsigned char year = 21; // 年份为2021年 unsigned char month = 1; // 月份为1月 unsigned char day = 1; // 日为1日 init_lcd(); // 初始化LCD1602 while(1) { display_date(year, month, day); // 在LCD1602上显示日期 // 下面的代码用于更新日期 day++; if(month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) // 判断闰年 { if(day > day_leap_table[month - 1]) { day = 1; month++; } } else { if(day > day_table[month - 1]) { day = 1; month++; } } if(month > 12) { month = 1; year++; } } } // 初始化LCD1602 void init_lcd(void) { display_char(0, 0, 0x38); // 显示模式设置 display_char(0, 0, 0x0c); // 显示开关控制 display_char(0, 0, 0x06); // 显示光标移动设置 display_char(0, 0, 0x01); // 显示清屏 } // 在LCD1602指定位置显示一个字符 void display_char(unsigned char x,unsigned char y,unsigned char dat) { unsigned char addr; if(y == 0) { addr = 0x80 + x; } else { addr = 0xc0 + x; } delay(1); RS = 0; RW = 0; LCD1602_DATAPINS_7 = dat >> 7; LCD1602_DATAPINS_6 = (dat >> 6) & 0x01; LCD1602_DATAPINS_5 = (dat >> 5) & 0x01; LCD1602_DATAPINS_4 = (dat >> 4) & 0x01; EN = 1; delay(1); EN = 0; delay(1); RS = 0; RW = 0; LCD1602_DATAPINS_7 = (dat >> 3) & 0x01; LCD1602_DATAPINS_6 = (dat >> 2) & 0x01; LCD1602_DATAPINS_5 = (dat >> 1) & 0x01; LCD1602_DATAPINS_4 = dat & 0x01; EN = 1; delay(1); EN = 0; } // 在LCD1602指定位置显示一个字符串 void display_string(unsigned char x,unsigned char y,unsigned char *s) { while(*s != 0) { display_char(x, y, *s++); x++; } } // 在LCD1602指定位置显示日期 void display_date(unsigned char year,unsigned char month,unsigned char day) { unsigned char date_str[11]; unsigned char i; // 计算日期字符串 date_str[0] = '2'; date_str[1] = '0'; date_str[2] = year / 10 + '0'; date_str[3] = year % 10 + '0'; date_str[4] = '-'; date_str[5] = month / 10 + '0'; date_str[6] = month % 10 + '0'; date_str[7] = '-'; date_str[8] = day / 10 + '0'; date_str[9] = day % 10 + '0'; date_str[10] = 0; display_string(0, 0, date_str); // 在LCD1602上显示日期 } // 延时函数 void delay(unsigned int i) { unsigned int j,k; for(j=0;j<i;j++) { for(k=0;k<125;k++); } } ``` 该程序使用LCD1602显示日期信息,通过更新日期实现万年历的功能。需要注意的是,该程序仅适用于2021年的日历,如果需要适用于其他年份,需要对程序进行相应的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值