求c51单片机电子钟程序(c语言)

求c51单片机电子钟程序(c语言),第1张

#include <reg51h>

#define uchar unsigned char //定义unsigned int为uint

#define uint unsigned int //定义unsigned uchar为uchar

sbit LCD_RS = P2^0 ;

sbit LCD_RW = P2^1 ;

sbit LCD_EN = P2^2 ;

sbit D_SDA = P2^6; //定义74HC164数据线为P26端口

sbit D_SCL = P2^7; //定义74HC164数据线为P27端口

sbit CLK = P1^3; /实时时钟时钟线引脚 /

sbit IO = P1^4; /实时时钟数据线引脚 /

sbit RST = P1^5; /实时时钟复位线引脚 /

sbit ACC0 = ACC^0;

sbit ACC7 = ACC^7;

uchar time[8] = {0x50,0x30,0x19,0x30,0x12,0x06,0x06};

//========= 延时函数 ============

//延时时间以1ms为单位

//s决定延时时间长短

void delay_ms(uint s)

{

uint x;

for(s;s>0;s--)

{

x = 200;

while(x--);

}

}

//========= 送出一个字节给74HC164(实现串并转换) ==========

void send_out(unsigned char out)//传送一个字节8位

{

uchar i;

D_SCL = 0;

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

{

D_SDA = out&0x80; //送数据到数据口

D_SCL = 1; //时钟线置1

D_SCL = 0; //送一时钟

out<<=1; //左移

}

}

//========= 写命令函数 ==========

void lcd_wcmd(uchar cmd)

{

LCD_RS = 0;

LCD_RW = 0;

LCD_EN = 0;

send_out(cmd);

LCD_EN = 1;

LCD_EN = 0 ;

}

//========= 写数据函数 ==========

void lcd_wdat(uchar dat)

{

LCD_RS = 1;

LCD_RW = 0;

LCD_EN = 0;

send_out(dat);

LCD_EN = 1;

LCD_EN = 0;

}

//========= LCD初始化函数 ==========

void lcd_init()

{

lcd_wcmd(0x38);

delay_ms(1);

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

delay_ms(1);

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

delay_ms(1);

lcd_wcmd(0x01); //清除LCD显示屏

delay_ms(1);

}

//========== 往DS1302写入1Byte数据 (内部函数) =============

void w_byte(uchar dat)

{

uchar i;

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

{

IO = dat & 0x01;

CLK = 1;

CLK = 0;

dat = dat >> 1;

}

}

//======== 从DS1302读取1Byte数据 (内部函数) ===================

uchar r_byte(void)

{

uchar i;

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

{

ACC = ACC >> 1;

ACC7 = IO;

CLK = 1;

CLK = 0;

}

return(ACC);

}

//========== 指定地址往DS1302写入1Byte数据 (内部函数) =============

void write_byte(uchar addr, uchar dat)

{

RST = 0;

CLK = 0;

RST = 1;

w_byte(addr);

w_byte(dat);

CLK = 1;

RST = 0;

}

//========== 指定地址往DS1302读1Byte数据 (内部函数) =============

uchar read_byte(uchar addr)

{

uchar ucData;

RST = 0;

CLK = 0;

RST = 1;

w_byte(addr);

ucData = r_byte();

CLK = 1;

RST = 0;

return(ucData);

}

//============ 设置ds1302日期和时间 =============

void write_ds1302(uchar p)

{

uchar i;

uchar addr = 0x80;

write_byte(0x8e,0x00); // 控制命令,WP=0,写 *** 作

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

{

write_byte(addr,p); // 秒 分 时 日 月 星期 年

p++;

addr +=2;

}

write_byte(0x8e,0x80); // 控制命令,WP=1,写保护

}

//============ 读ds1302当前日期和时间 =============

void read_ds1302(uchar p)

{

uchar i;

uchar addr = 0x81;

for (i=0; i<7; i++)

{

p = read_byte(addr); //格式为: 秒 分 时 日 月 星期 年

addr += 2;

p++;

}

}

//============ 显示函数 ===================

void lcd_disp()

{

uchar addr = 4;

lcd_wcmd(0x80 + addr);

lcd_wdat(((time[2]>>4)&0x0f)+0x30); //显示小时

addr++;

lcd_wcmd(0x80 + addr);

lcd_wdat((time[2]&0x0f)+0x30);

addr++;

lcd_wcmd(0x80 + addr);

lcd_wdat(':'); //显示":"

addr++;

lcd_wcmd(0x80 + addr);

lcd_wdat(((time[1]>>4)&0x0f)+0x30); //显示分

addr++;

lcd_wcmd(0x80 + addr);

lcd_wdat((time[1]&0x0f)+0x30);

addr++;

lcd_wcmd(0x80 + addr);

lcd_wdat(':'); //显示":"

addr++;

lcd_wcmd(0x80 + addr);

lcd_wdat(((time[0]>>4)&0x0f)+0x30); //显示秒

addr++;

lcd_wcmd(0x80 + addr);

lcd_wdat((time[0]&0x0f)+0x30);

addr = 2;

lcd_wcmd(0xc0 + addr); //在第二行显示年月日和星期

lcd_wdat('2'); //显示2

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat('0'); //显示0

addr++;

lcd_wdat(((time[6]>>4)&0x0f)+0x30); //年

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat((time[6]&0x0f)+0x30);

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat(' ');

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat(((time[4]>>4)&0x0f)+0x30); //显示月

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat((time[4]&0x0f)+0x30);

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat(' ');

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat(((time[3]>>4)&0x0f)+0x30); //显示日

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat((time[3]&0x0f)+0x30);

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat(' ');

addr++;

lcd_wcmd(0xc0 + addr);

lcd_wdat((time[5]&0x0f)+0x30); //显示星期

}

//=========== 主函数 ===============

void main()

{

lcd_init(); // 初始化LCD

write_ds1302(time);

while(1)

{

read_ds1302(time); //读DS1302数据

lcd_disp(); //LCD显示

delay_ms(500); //延时05秒

}

}

这是一个电子时钟,在LCD1602上显示,时钟芯片是DS1302

以下是四位数码管可调时带秒闪烁的c51单片机电子钟程序(c语言)。

/ 本程序中,晶振为12MHz, /

/ 时间控制采用定时中断控制方式。 /

/ 模式和时间调整采用查询方式。 /

#include<reg52h>

sbit P20=P2^0; //分个位控制端

sbit P21=P2^1; //分十位控制端

sbit P22=P2^2; //时个位控制端

sbit P23=P2^3; //时十位控制端

sbit led=P2^7; //second display led

sbit key0=P3^0; //模式设置

sbit key1=P3^1; //加

sbit key2=P3^2; //减

unsigned char hour,min,sec,T50ms;

unsigned char modstate; //模式状态

unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//段码

void init(); //初始化子程序声明

void delay500us(unsigned char X); //延时子程序声明

void display(); //显示子程序声明

void display001(); //显示子程序声明

void display002(); //显示子程序声明

void keyscan(); //按键识别子程序声明

void main()

{

init();

while(1)

{

keyscan();

}

}

void init() //初始化子程序

{

TMOD=0x01;

TH0=(65536-49990)/256;

TL0=(65536-49990)%256;

ET0=1;

EA=1;

TR0=1;

}

void delay500us(unsigned char X)

{

unsigned char i,j;

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

for(j=248;j>0;j--);

}

void timer0() interrupt 1 //timer0中断服务子程序,定时时间为50ms,本程序加了10us的时间修正量

{

TMOD=0x01;

TH0=(65536-49990)/256;

TL0=(65536-49990)%256;

T50ms++;

if(T50ms>=20)

{

T50ms=0;

sec++;

if(sec>=60)

{

sec=0;

min++;

if(min>=60)

{

min=0;

hour++;

if(hour>=24)hour=0;

}

}

}

}

void display()

{

P20=1;

P21=1;

P22=1;

P23=1;

P0=table[hour/10];

P23=0;

delay500us(5);

P20=1;

P21=1;

P22=1;

P23=1;

P0=table[hour%10];

P22=0;

delay500us(5);

P20=1;

P21=1;

P22=1;

P23=1;

P0=table[min/10];

P21=0;

delay500us(5);

P20=1;

P21=1;

P22=1;

P23=1;

P0=table[min%10];

P20=0;

delay500us(5);

if(T50ms<=10)led=0;

if(T50ms>10)led=1;

}

void display001()

{

P20=1;

P21=1;

P22=1;

P23=1;

P0=table[hour/10];

P23=0;

delay500us(10);

P20=1;

P21=1;

P22=1;

P23=1;

P0=table[hour%10];

P22=0;

delay500us(10);

}

void display002()

{

P20=1;

P21=1;

P22=1;

P23=1;

P0=table[min/10];

P21=0;

delay500us(10);

P20=1;

P21=1;

P22=1;

P23=1;

P0=table[min%10];

P20=0;

delay500us(10);

}

void keyscan() //按键识别钟程序

{

while(modstate==0)

{

display();

if(key0==0)

{

display();

if(key0==0)modstate++; //这两句加在一起为延时10ms软件防抖设计。

while(key0==0)display001(); //等待按键释放。

}

}

////

while(modstate==1)

{

display001();

if(key0==0)

{

display001();

if(key0==0)modstate++; //这两句加在一起为延时10ms软件防抖设计。

while(key0==0)display002(); //等待按键释放。

}

if(key1==0)

{

display001();

if(key1==0)

{

hour++;

if(hour>=24)hour=0;

while(key1==0)display001();

}

}

if(key2==0)

{

display001();

if(key2==0)

{

hour--;

if(hour>=24)hour=0;

while(key2==0)display001();

}

}

}

////

while(modstate==2)

{

display002();

if(key0==0)

{

display002();

if(key0==0)modstate=0; //这两句加在一起为延时10ms软件防抖设计。

while(key0==0)display(); //等待按键释放。

}

if(key1==0)

{

display002();

if(key1==0)

{

min++;

if(min>=60)min=0;

while(key1==0)display002();

}

}

if(key2==0)

{

display002();

if(key2==0)

{

min--;

if(min>=60)min=0;

while(key2==0)display002();

}

}

}

}

C51是基于标准的C语言扩展而来的,所以,标准C语言能做的东西,C51也可以。

平方运算,自不必说,就是两个数相乘:

例如:float a,b,c; c = ab;

开方,则需要用到库函数:

标准c语言里用的是 sqrt()函数,这个函数包含在mathh文件中。

所以:

#include <mathh>

c = sqrt(a);

就可以了

sbit dula=P2^6;//段锁存器锁存湍

sbit wela=P2^7;;//位锁存器锁存湍

char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,

0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};

void display(shiwan_c,wan_c,qian_c,bai_c,shi_c,ge_c)//6位显示子程序

{

P0=table[shiwan_c]; //显示十万位

dula=1;

dula=0;

P0=0xfe;

wela=1;

wela=0;

delay(2);

P0=table[wan_c]; //显示万位

dula=1;

dula=0;

P0=0xfd;

wela=1;

wela=0;

delay(2);

P0=table[qian_c]; //显示千位

dula=1;

dula=0;

P0=0xfb;

wela=1;

wela=0;

delay(2);

P0=table[bai_c]; //显示百位

dula=1;

dula=0;

P0=0xf7;

wela=1;

wela=0;

delay(2);

P0=table[shi_c]; //显示十位

dula=1;

dula=0;

P0=0xef;

wela=1;

wela=0;

delay(2);

P0=table[ge_c]; //显示个位

dula=1;

dula=0;

P0=0xdf;

wela=1;

wela=0;

delay(2);

P0=0xff; //显示完毕后关闭最后一位显示

wela=1;

wela=0;

}

以上程序需放在循环程序中,数码管需反复显示

如果其中两位不需显示,可赋值为16

问题1)你所谓的同时工作是指led亮的同时数码管也在显示,是这样的吗?单片机跑的程序都是单线程的,所以函数可能会受到中断的影响

问题2)理论上,位选和段选是不要求顺序的,如果交换顺序会出现不一样的效果,说明你的程序写的有问题,根据你说的现象,我认为你段选和位选没设置好

#include<reg52h>

unsigned char code table[] ={" "};

unsigned char code table1[]={" : "};

sbit rs=P1^2;

sbit lcden=P1^0;

unsigned char flag,m;

void delay(int xms)

{

int i,j;

for(i=xms;i>0;i--) //i=xms即延时约xms毫秒

for(j=110;j>0;j--);

}

void write_com(unsigned char com)

{//写液晶命令函数

rs=0;

lcden=0;

P2=com;

delay(3);

lcden=1;

delay(3);

lcden=0;

}

void write_date(unsigned char date)

{//写液晶数据函数

rs=1;

lcden=0;

P2=date;

delay(3);

lcden=1;

delay(3);

lcden=0;

}

void init()

{//初始化函数

unsigned char num;

lcden=0;

rs=0;

write_com(0x38);//1602液晶初始化

write_com(0x0c);

write_com(0x06);

write_com(0x01);

write_com(0x80);

for(num=0;num<15;num++)//写入液晶固定部分显示

{

write_date(table[num]);

delay(3);

}

write_com(0x80+0x40);

for(num=0;num<5;num++)

{

write_date(table1[num]);

delay(3);

}

}

void write_dianya(unsigned char add,unsigned char date)

{//1602液晶刷新时分秒函数4为时,7为分,10为秒

unsigned char bai,shi,ge;

bai=date/100;

shi=date%100/10;

ge=date%10;

write_com(0x80+0x40+add);

write_date(0x30+bai);

write_date(0x30+shi);

write_date(0x30+ge);

}

void main ()

{

init();

TMOD=0x20; //设置定时器1工作方式2

TH1=0xfd;

TL1=0xfd;

TR1=1;

REN=1; //设置串行口工作方式

SM0=0;

SM1=1;

EA=1; //中断设置

ES=1;

while(1)

{

if(flag==1)

{

ES=0;

SBUF=m;

while(!TI);

TI=0;

ES=1;

}

}

}

void ser() interrupt 4

{

RI=0;

m=SBUF;

write_dianya(5,m);

flag=1;

}

以上就是关于求c51单片机电子钟程序(c语言)全部的内容,包括:求c51单片机电子钟程序(c语言)、51单片机求这个时钟的c语言程序、C51单片机怎么用C语言实现数值的开方和平方运算等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/9425065.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存