单片机的时钟按键程序

如何编写程序能让按键按下弹起来再加一,我的程序按键按下就会一直加,反应太快

4个回答

防抖,判断到端口高电平之后,延时10ms左右,再判断一次是否还是刚刚的高电平状态,如果是,再等待按键释放,即while(!key);。跳出这个循环之后就表示按键事件完成。
if(!key)
{
delay(10);//延迟10ms
if(!key)//再判断,防抖 {
while(key);//等待释放
LED = ~LED;
}
}

使用边沿触发。
如果按下是低电平,就用上升沿触发;
如果按下是高电平,就用下降沿触发。

用定时器扫描按键就可以可

你让它等待释放后才加1

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
基于凌阳单片机的数字时钟程序

以SPCE061A单片机为主控系统,通过硬件电路制作以及软件程序编制,设计一个多功能数字时钟,该时钟由时钟模块、语音模块、SPLC501液晶显示模块、按键模块、温度传感器DS18B20模块。该系统操作简单可以实现准确显示时间,整点报时,调整时间,温度显示,闹钟,秒表功能。该时钟功耗小,成本低,实用性强,系统具有一定的扩展性。

关于AT89C51单片机数字时钟的设计C语言程序warning问题

本人新手,还希望各位大大帮忙看下怎么解决 Build target 'Target 1' assembling STARTUP.A51... linking... *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL SYMBOL: ?C_START MODULE: STARTUP.obj (?C_STARTUP) *** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL SYMBOL: ?C_START MODULE: STARTUP.obj (?C_STARTUP) ADDRESS: 080AH Program Size: data=9.0 xdata=0 code=15 "t" - 0 Error(s), 2 Warning(s). 源程序如下: #include<reg52.h> #define uint unsigned int #define uchar unsigned char sbit QB1=P1^0; sbit QB2=P1^1; //数码管段选 sbit QB3=P1^2; sbit QB4=P1^3; sbit QB5=P1^4; sbit QB6=P1^5; sbit fm=P1^6; //蜂鸣器 sbit s1=P2^4; //s5按键,切换显示 sbit s2=P2^3; //s2按键,设置调时 sbit s3=P2^2; //s3按键,加1 sbit s4=P2^1; //s4按键,减1 sbit led1=P0^0; sbit led2=P0^1; sbit led3=P0^2; uchar count; uchar sec,minu,hour,day,week,mon; uchar n_sec,n_minu,n_hour; uint year; uchar set_2=1,set_1=1; uchar hs,hg,mis,mig,ss,sg; uchar nhs,nhg,nms,nmg,nss=0,nsg=0; uchar ms,mg,ds,dg,w; uchar code table[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80, 0X90,0X88,0X83,0XC6,0XA1,0X8E,0X86,0xbf}; //0~F,-,共阳 //uchar code tableyi[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, //0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};//0-F,-,共阴 uchar code table_d[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd, 0x87,0xff,0xef}; //0~9数组,带小数点 uchar table1[]={31,31,29,31,30,31,30,31,31,30,31,30,31}; //闰年 uchar table2[]={31,31,28,31,30,31,30,31,31,30,31,30,31}; //非闰年 void delay(uint); //延时函数 void timer0(); //走时中断函数 void jishi(); //计时函数 void key_change(); //切换显示按键函数 void key_set(); //设置时间按键函数 void disp(uchar,uchar,uchar,uchar,uchar,uchar); //显示函数 void zd_clock(); //整点报时函数 void nz_clock(); //闹钟函数 uchar incone(uchar); //加1函数 uchar decone(uchar); //减1函数 void set_time(); //设置时间函数 void set_clock(); //设置闹钟函数 void set_mdw(); //设置月日星期函数 void main() //主函数 { EA=1; ET0=1; TR0=1; TMOD=0x01; TH0=0x4c; //50ms初值 晶振11.0592 TL0=0x00; hour=23;minu=59;sec=49; //赋初值:11点59分0秒 n_hour=12;n_minu=56;n_sec=0; //闹钟赋初值12点1分0秒 year=2008;mon=5;day=14;week=3;//年月日星期赋初值2008年5月11日星期天;祝天下所有母亲节日快乐 while(1) { hs=hour/10; //时分秒HH.MM.SS hg=hour%10; mis=minu/10; mig=minu%10; ss=sec/10; sg=sec%10; ms=mon/10; //月日-星期MM.DD.-W mg=mon%10; ds=day/10; dg=day%10; w=week; nhs=n_hour/10; //闹钟定时HH.MM.SS nhg=n_hour%10; nms=n_minu/10; nmg=n_minu%10; nss=n_sec/10; nsg=n_sec%10; key_change(); //s4按键扫描 key_set(); //s2按键扫描 set_time(); //设置时间 set_mdw(); //设置月日星期 set_clock(); //设置闹钟 if(set_1==1) //正常走时显示 { disp(hs,hg,mis,mig,ss,sg); } if(set_1==2) //设置时间,LED1闪亮 { disp(hs,hg,mis,mig,ss,sg); if(sec%2==0) {led2=1;led3=1;led1=~led1;} // else // {led1=1;} } if(set_1==3) //正常显示月日-星期 { disp(ms,mg,ds,dg,16,w); } if(set_1==4) //设置月日-星期,LED2闪亮 { disp(ms,mg,ds,dg,16,w); if(sec%2==0) {led1=1;led3=1;led2=~led2;} // else // {led2=1;} } if(set_1==5) //正常显示定时 { disp(nhs,nhg,nms,nmg,nss,nsg); } if(set_1==6) //设置闹钟定时,LED3闪亮 { disp(nhs,nhg,nms,nmg,nss,nsg); if(sec%2==0) {led1=1;led2=1;led3=~led3;} // else // {led3=1;} } zd_clock(); //整点报时 nz_clock(); //闹钟 } } void timer0() interrupt 1 //50ms中断函数 { TMOD=0x01; TH0=0x4c; //50ms初值 晶振11.0592 TL0=0x00; count++; if(count==20) { count=0; sec++; jishi(); //调计时函数 } } void jishi() //计时函数 { if(sec==60) { sec=0; minu++; if(minu==60) { minu=0; hour++; if(hour==24) { hour=0; day++; week++; if(week==8) {week=0;} if(year%4==0&&year%100!=0||year%400==0) //闰年 { if(day==table1[mon]+1) { day=0; mon++; if(mon==13) {mon=0;year++;} } } else //非闰年 { if(day==table2[mon]+1) { day=0; mon++; if(mon==13) {mon=0;year++;} } } } } } } void key_change() //s1按键扫描 { if(s1==0) { delay(200); if(s1==0) { set_1++; while(!s1); if(set_1==7) {set_1=1;} } } } void key_set() //s2按键扫描 { if(s2==0) { delay(10); if(s2==0) { set_2++; while(!s2); if(set_2==4) {set_2=1;} } } } void disp(uchar a1,uchar a2,uchar a3,uchar a4,uchar a5,uchar a6) //显示函数 { QB1=1; QB2=0; QB3=0; QB4=0; QB5=0; QB6=0; P3=table[a1]; //段码送P0口 delay(10); //延时一小会 QB1=0; QB2=1; QB3=0; QB4=0; QB5=0; QB6=0; P3=table[a2]; //第2个数码管显示,带小数点 delay(10); QB1=0; QB2=0; QB3=1; QB4=0; QB5=0; QB6=0; P3=table[a3]; //第3个数码管显示 delay(10); QB1=0; QB2=0; QB3=0; QB4=1; QB5=0; QB6=0; P3=table[a4]; //第4个数码管显示,带小数点 delay(10); QB1=0; QB2=0; QB3=0; QB4=0; QB5=1; QB6=0; //第5个数码管显示 P3=table[a5]; delay(10); QB1=0; QB2=0; QB3=0; QB4=0; QB5=0; QB6=1; P3=table[a6]; //第6个数码管显示 delay(10); QB1=0; QB2=0; QB3=0; QB4=0; QB5=0; QB6=0; } void zd_clock() //整点报时函数 { if(minu==59&&(sec==53||sec==55||sec==57)) { fm=0; delay(5); fm=1; delay(5); } fm=0; if(minu==59&&sec==59) { fm=0; delay(5); fm=1; delay(5); fm=0; } } void nz_clock() //闹钟函数 { if(hour==n_hour&&minu==n_minu&&sec==n_sec) //if((sec%2==0)&&sec<30) { fm=0; delay(1); fm=1; delay(1); } } void set_time() //设置时间函数 { if(set_1==2) { if(set_2==1) { hour=incone(hour); if(hour==24) {hour=0;} // if(hour<0) // {hour=23;} hour=decone(hour); } if(set_2==2) { minu=incone(minu); if(minu==60) {minu=0;} // if(minu<0) // {minu=59;} minu=decone(minu); } } } void set_mdw() //设置月日星期函数 { if(set_1==4) { if(set_2==1) { mon=incone(mon); if(mon==13) {mon=1;} mon=decone(mon); // if(mon==0) // {mon=12;} } if(set_2==2) { day=incone(day); if(day==32) {day=0;} day=decone(day); // if(day==0) // {day=0;} } if(set_2==3) { week=incone(week); if(week==8) {week=0;} week=decone(week); // if(week==0) // {week=7;} } } } void set_clock() //设置闹钟函数 { if(set_1==6) { if(set_2==1) { n_hour=incone(n_hour); if(n_hour==24) {n_hour=0;} n_hour=decone(n_hour); if(n_hour==0) {n_hour=0;} } if(set_2==2) { n_minu=incone(n_minu); if(n_minu==60) {n_minu=0;} n_minu=decone(n_minu); if(n_minu==0) {n_minu=0;} } } } uchar incone(uchar n) //加1函数 { if(s3==0) { delay(200); if(s3==0) { n++; while(!s3); } } return(n); } uchar decone(uchar m) //减1函数 { if(s4==0) { delay(200); if(s4==0) { m--; while(!s4); if(m<0) {m=0;} } } return(m); } void delay(uint k) //延时函数 { uint i,j; for(i=k;i>0;i--) for(j=80;j>0;j--); }

我编了一个单片机的时钟程序,想要实现串口改变时间,可是不知道应该怎么编入串口求解答

这是我编的,其中串口的引入是错误的求改正 #include<reg51.h>#define uint unsigned int#define uchar unsigned char uchar hour,min,sec,temp;uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; void delay(uint z);void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f);void time_change();void main(){ hour=00; min=0; sec=0; SCON=0x50; PCON = 0x00; TMOD=0x21; TH0=(65536-50000)/256; TL0=(65536-50000)%256; TH1=0xfd; TL1=0xfd; EA=1; ES=1; ET0=1; ET1=0; TR0=1; TR1=1; delay(50); while(1) { time_change(); display(table[hour/10],table[hour%10],table[min/10],table[min%10],table[sec/10],table[sec%10]); }}void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f){ P1=0x01;P0=a;delay(2); P1=0x02;P0=b;delay(2); P1=0x08;P0=c;delay(2); P1=0x10;P0=d;delay(2); P1=0x40;P0=e;delay(2); P1=0x80;P0=f;delay(2); P1=0x04;P0=0xbf;delay(2); P1=0x20;P0=0xbf;delay(2);}void timer0() interrupt 1{ TH0=(65536-50000)/256; TL0=(65536-50000)%256; temp++; }void revdata(void) interrupt 4{ ES=0; if(RI==1){RI=0;hour=SBUF;}delay(50); if(RI==1){RI=0;min=SBUF;}delay(50); if(RI==1){RI=0;sec=SBUF;}delay(50); ES=1;}void delay(uint z){ uint j,k; for(j=z;j>0;j--) for(k=120;k>0;k--);}void time_change(){ if(temp>=20) { temp=0; sec++; if(sec>=60) { sec=0; min++; if(min>=60) { min=0; hour++; if(hour>=24) { hour=0; } } } }}

12864显示时钟,按键可调整时间的程序怎么写啊??

1.DB1~DB7是P0^0~P0^6 #define LCD_data P0 //数据口 sbit LCD_RS = P1^0; //寄存器选择输入 sbit LCD_RW = P1^1; //液晶读/写控制 sbit LCD_EN = P2^5; //液晶使能控制 sbit LCD_PSB = P1^2; //串/并方式控制 sbit LCD_RST = P1^4; //液晶复位端口

C51单片机 12Hz 1000ms延时程序(c语言)

哪位大神可以细致的讲讲51单片机中,12Hz晶振,延时计算程序的算法(1000ms最好)单片机小白表示没有学会呜呜呜~ 看一个延迟10ms程序的代码,for循环中的计算方法没有懂,不会计算 void delayms(uchar ms) { uchar i; while(ms--) { for(i=0;i<120;i++); } } 这个10ms的计算公式是怎样的,如果换成1000ms又该怎样计算ne

单片机编程按键与实际按键正好颠倒

#include<absacc.h> #define LEDLen 6 #define mode 0x03; #define CAddr XBYTE[0xe100]/* 控制字地址 */ #define OUTBIT XBYTE[0xe101]/* 位控制口 */ #define CLK164 XBYTE[0xe102]/* 段控制口(接164时钟位) */ #define DAT164 XBYTE[0xe102] /* 段控制口(接164数据位) */ #define IN XBYTE[0xe103] /* 键盘读入口 */ unsigned char LEDBuf[LEDLen]; /* 显示缓冲 */ code unsigned char LEDMAP[] = { /* 八段管显示码 */ 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 }; void Delay(unsigned char CNT) { unsigned char i; while (CNT-- !=0) for (i=100; i !=0; i--); } void DisplayLED() { unsigned char i, j; unsigned char Pos; unsigned char LED; Pos = 0x20; /* 从左边开始显示 */ for (i = 0; i < LEDLen; i++) { OUTBIT = 0; /* 关所有八段管 */ LED = LEDBuf[i]; for (j = 0; j < 8; j++) { /* 送164 */ if (LED & 0x80) DAT164 = 1; else DAT164 = 0; CLK164 = CLK164|0x02; CLK164 = CLK164&0xfd; LED <<= 1; } OUTBIT = Pos; /* 显示一位八段管 */ Delay(1); Pos >>= 1; /* 显示下一位 */ } } code unsigned char KeyTable[] = { /* 键码定义 */ 0x00, 0x01, 0x04, 0x07 , 0x0f, 0x02, 0x05, 0x08, 0x0e, 0x03, 0x06, 0x09 , 0x0d, 0x0c, 0x0b, 0x0a , 0x10,0x11,0x12,0x13,0x14, 0x15,0x16, }; unsigned char TestKey() { OUTBIT = 0; /* 输出线置为0 */ return (~IN & 0x0f); /* 读入键状态 (高四位不用) */ } unsigned char GetKey() { unsigned char Pos; unsigned char i; unsigned char k; i = 6; Pos = 0x20; /* 找出键所在列 */ do { OUTBIT = ~ Pos; Pos >>= 1; k = ~IN & 0x0f; } while ((--i != 0) && (k == 0)); /* 键值 = 列 X 4 + 行 */ if (k != 0) { i *= 4; if (k & 2) i += 1; else if (k & 4) i += 2; else if (k & 8) i += 3; OUTBIT = 0; do Delay(10); while (TestKey()); /* 等键释放 */ return(KeyTable[i]); /* 取出键码 */ } else return(0xff); } void main() { CAddr = mode; LEDBuf[0] = 0xff; LEDBuf[1] = 0xff; LEDBuf[2] = 0xff; LEDBuf[3] = 0xff; LEDBuf[4] = 0x00; LEDBuf[5] = 0x00; while (1) { DisplayLED(); if (TestKey()) LEDBuf[5] = LEDMAP[GetKey() & 0x0f]; } } 程序如上 为什么按键会上下颠倒?

帮我改C语言代码(51单片机LCD1602显示时间从k1这些按键控制变成矩阵按键控制)

帮我改C语言代码,51单片机LCD1602显示时间从k1这些按键控制变成矩阵按键控制(现在是可以用k1这些按键来修改了) 原理图: ![图片说明](https://img-ask.csdn.net/upload/201912/22/1577010044_884857.png) ![图片说明](https://img-ask.csdn.net/upload/201912/22/1577010062_997331.png) 下面是代码: ``` //下面是main.c代码 /******************************************************************************* * 实验名 : 万年历实验 * 使用的IO : * 实验效果 :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择 *选择设置加1。 * 注意 : *******************************************************************************/ #include<reg51.h> #include"lcd.h" #include"ds1302.h" sbit K1=P3^1; sbit K2=P3^0; sbit K3=P3^2; sbit K4=P3^3; //管脚接线 void Int0Configuration(); void LcdDisplay(); unsigned char SetState,SetPlace; void Delay10ms(void); //误差 0us /******************************************************************************* * 函数名 : main * 函数功能 : 主函数 * 输入 : 无 * 输出 : 无 *******************************************************************************/ void main() { unsigned char i; Int0Configuration(); LcdInit(); Ds1302Init(); while(1) { if(SetState==0) { Ds1302ReadTime(); } else { if(K1==0) //检测按键K1是否按下 { Delay10ms(); //消除抖动 if(K1==0) { SetPlace++; if(SetPlace>=7) SetPlace=0; } while((i<50)&&(K1==0)) //检测按键是否松开 { Delay10ms(); i++; } i=0; } if(K2==0) //检测按键K2是否按下 { Delay10ms(); //消除抖动 if(K2==0) { TIME[SetPlace]++; if((TIME[SetPlace]&0x0f)>9) //换成BCD码。 { TIME[SetPlace]=TIME[SetPlace]+6; } if((TIME[SetPlace]>=0x60)&&(SetPlace<2)) //分秒只能到59 { TIME[SetPlace]=0; } if((TIME[SetPlace]>=0x24)&&(SetPlace==2)) //小时只能到23 { TIME[SetPlace]=0; } if((TIME[SetPlace]>=0x32)&&(SetPlace==3)) //日只能到31 { TIME[SetPlace]=0; } if((TIME[SetPlace]>=0x13)&&(SetPlace==4)) //月只能到12 { TIME[SetPlace]=0; } if((TIME[SetPlace]>=0x7)&&(SetPlace==5)) //周只能到7 { TIME[SetPlace]=1; } // if(SetPlace==5) //月只能到12 // { // TIME[SetPlace]=; // } } while((i<50)&&(K2==0)) //检测按键是否松开 { Delay10ms(); i++; } i=0; } } LcdDisplay(); } } /******************************************************************************* * 函数名 : LcdDisplay() * 函数功能 : 显示函数 * 输入 : 无 * 输出 : 无 *******************************************************************************/ void LcdDisplay() { LcdWriteCom(0x80+0X40); LcdWriteData('0'+TIME[2]/16); //时 LcdWriteData('0'+(TIME[2]&0x0f)); LcdWriteData('-'); LcdWriteData('0'+TIME[1]/16); //分 LcdWriteData('0'+(TIME[1]&0x0f)); LcdWriteData('-'); LcdWriteData('0'+TIME[0]/16); //秒 LcdWriteData('0'+(TIME[0]&0x0f)); LcdWriteCom(0x80); LcdWriteData('2'); LcdWriteData('0'); LcdWriteData('0'+TIME[6]/16); //年 LcdWriteData('0'+(TIME[6]&0x0f)); LcdWriteData('-'); LcdWriteData('0'+TIME[4]/16); //月 LcdWriteData('0'+(TIME[4]&0x0f)); LcdWriteData('-'); LcdWriteData('0'+TIME[3]/16); //日 LcdWriteData('0'+(TIME[3]&0x0f)); LcdWriteCom(0x8D); LcdWriteData('0'+(TIME[5]&0x07)); //星期 } /******************************************************************************* * 函数名 : Int0Configuration() * 函数功能 : 配置外部中断0 * 输入 : 无 * 输出 : 无 *******************************************************************************/ void Int0Configuration() { //设置INT0 IT0=1;//跳变沿出发方式(下降沿) EX0=1;//打开INT0的中断允许。 EA=1;//打开总中断 } /******************************************************************************* * 函数名 : Int0() * 函数功能 : 外部中断0 中断函数 * 输入 : 无 * 输出 : 无 *******************************************************************************/ void Int0() interrupt 0 { Delay10ms(); if(K3==0) { SetState=~SetState; SetPlace=0; Ds1302Init(); } } /******************************************************************************* * 函数名 : Delay10ms * 函数功能 : 延时函数,延时10ms * 输入 : 无 * 输出 : 无 *******************************************************************************/ void Delay10ms(void) //误差 0us { unsigned char a,b,c; for(c=1;c>0;c--) for(b=38;b>0;b--) for(a=130;a>0;a--); } //下面为ds1302.c代码 #include"ds1302.h" //---DS1302写入和读取时分秒的地址命令---// //---秒分时日月周年 最低位读写位;-------// uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---// //---存储顺序是秒分时日月周年,存储格式是用BCD码---// uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13}; /******************************************************************************* * 函 数 名 : Ds1302Write * 函数功能 : 向DS1302命令(地址+数据) * 输 入 : addr,dat * 输 出 : 无 *******************************************************************************/ void Ds1302Write(uchar addr, uchar dat) { uchar n; RST = 0; _nop_(); SCLK = 0;//先将SCLK置低电平。 _nop_(); RST = 1; //然后将RST(CE)置高电平。 _nop_(); for (n=0; n<8; n++)//开始传送八位地址命令 { DSIO = addr & 0x01;//数据从低位开始传送 addr >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0; _nop_(); } for (n=0; n<8; n++)//写入8位数据 { DSIO = dat & 0x01; dat >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0; _nop_(); } RST = 0;//传送数据结束 _nop_(); } /******************************************************************************* * 函 数 名 : Ds1302Read * 函数功能 : 读取一个地址的数据 * 输 入 : addr * 输 出 : dat *******************************************************************************/ uchar Ds1302Read(uchar addr) { uchar n,dat,dat1; RST = 0; _nop_(); SCLK = 0;//先将SCLK置低电平。 _nop_(); RST = 1;//然后将RST(CE)置高电平。 _nop_(); for(n=0; n<8; n++)//开始传送八位地址命令 { DSIO = addr & 0x01;//数据从低位开始传送 addr >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0;//DS1302下降沿时,放置数据 _nop_(); } _nop_(); for(n=0; n<8; n++)//读取8位数据 { dat1 = DSIO;//从最低位开始接收 dat = (dat>>1) | (dat1<<7); SCLK = 1; _nop_(); SCLK = 0;//DS1302下降沿时,放置数据 _nop_(); } RST = 0; _nop_(); //以下为DS1302复位的稳定时间,必须的。 SCLK = 1; _nop_(); DSIO = 0; _nop_(); DSIO = 1; _nop_(); return dat; } /******************************************************************************* * 函 数 名 : Ds1302Init * 函数功能 : 初始化DS1302. * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds1302Init() { uchar n; Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能 for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年 { Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); } Ds1302Write(0x8E,0x80); //打开写保护功能 } /******************************************************************************* * 函 数 名 : Ds1302ReadTime * 函数功能 : 读取时钟信息 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds1302ReadTime() { uchar n; for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年 { TIME[n] = Ds1302Read(READ_RTC_ADDR[n]); } } //下面是lcd.c代码 #include"lcd.h" /******************************************************************************* * 函 数 名 : Lcd1602_Delay1ms * 函数功能 : 延时函数,延时1ms * 输 入 : c * 输 出 : 无 * 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。 *******************************************************************************/ void Lcd1602_Delay1ms(uint c) //误差 0us { uchar a,b; for (; c>0; c--) { for (b=199;b>0;b--) { for(a=1;a>0;a--); } } } /******************************************************************************* * 函 数 名 : LcdWriteCom * 函数功能 : 向LCD写入一个字节的命令 * 输 入 : com * 输 出 : 无 *******************************************************************************/ #ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时 void LcdWriteCom(uchar com) //写入命令 { LCD1602_E = 0; //使能 LCD1602_RS = 0; //选择发送命令 LCD1602_RW = 0; //选择写入 LCD1602_DATAPINS = com; //放入命令 Lcd1602_Delay1ms(1); //等待数据稳定 LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E = 0; } #else void LcdWriteCom(uchar com) //写入命令 { LCD1602_E = 0; //使能清零 LCD1602_RS = 0; //选择写入命令 LCD1602_RW = 0; //选择写入 LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); LCD1602_E = 0; // Lcd1602_Delay1ms(1); LCD1602_DATAPINS = com << 4; //发送低四位 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); LCD1602_E = 0; } #endif /******************************************************************************* * 函 数 名 : LcdWriteData * 函数功能 : 向LCD写入一个字节的数据 * 输 入 : dat * 输 出 : 无 *******************************************************************************/ #ifndef LCD1602_4PINS void LcdWriteData(uchar dat) //写入数据 { LCD1602_E = 0; //使能清零 LCD1602_RS = 1; //选择输入数据 LCD1602_RW = 0; //选择写入 LCD1602_DATAPINS = dat; //写入数据 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); //保持时间 LCD1602_E = 0; } #else void LcdWriteData(uchar dat) //写入数据 { LCD1602_E = 0; //使能清零 LCD1602_RS = 1; //选择写入数据 LCD1602_RW = 0; //选择写入 LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); LCD1602_E = 0; LCD1602_DATAPINS = dat << 4; //写入低四位 Lcd1602_Delay1ms(1); LCD1602_E = 1; //写入时序 Lcd1602_Delay1ms(5); LCD1602_E = 0; } #endif /******************************************************************************* * 函 数 名 : LcdInit() * 函数功能 : 初始化LCD屏 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ #ifndef LCD1602_4PINS void LcdInit() //LCD初始化子程序 { LcdWriteCom(0x38); //开显示 LcdWriteCom(0x0c); //开显示不显示光标 LcdWriteCom(0x06); //写一个指针加1 LcdWriteCom(0x01); //清屏 LcdWriteCom(0x80); //设置数据指针起点 } #else void LcdInit() //LCD初始化子程序 { LcdWriteCom(0x32); //将8位总线转为4位总线 LcdWriteCom(0x28); //在四位线下的初始化 LcdWriteCom(0x0c); //开显示不显示光标 LcdWriteCom(0x06); //写一个指针加1 LcdWriteCom(0x01); //清屏 LcdWriteCom(0x80); //设置数据指针起点 } #endif ```

关于51单片机制作时钟的问题?

用51单片机做时钟,我没用1302,就是一个简单的时钟,可以用6个数码管显示时分秒,可以用3个按键实现功能选择和加减。这些在开发板上都可以实现,之后我想在此基础上我想用AT24C02实现断电保护功能,当我的程序写完之后,发现无法实现,这个只能实现的是用按键控制的数字,比如我用按键将时间调成000019,之后让它自己往上加,然后我再断电,等我在上电的时候数码管上显示的还是000019,这个现象是属于断电保护还是代码出问题了,我有点不太清楚,代码如下,请求大家帮助。谢谢。 #include<reg52.h> sbit lsa=P2^2; sbit lsb=P2^3; sbit lsc=P2^4; sbit k1=P3^1; sbit k2=P3^0; sbit k3=P3^2; sbit SDA=P2^0; sbit SCL=P2^1; typedef unsigned int ui; typedef unsigned char uc; ui code shuju[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; ui disp[6]; ui num,shi,fen,miao; ui ss=0; void delay(ui i) { while(i--); } void Delay10us() { unsigned char a,b; for(b=1;b>0;b--) for(a=2;a>0;a--); } void I2cStart() { SDA=1; Delay10us(); SCL=1; Delay10us();//?????????SDA???????>4.7us SDA=0; Delay10us();//?????????>4us SCL=0; Delay10us(); } void I2cStop() { SDA=0; Delay10us(); SCL=1; Delay10us();//??????????4.7us SDA=1; Delay10us(); } void respons() { ui b; SCL=1; while(SDA)//????????????????豸??SDA???? { b++; if(b>200) //???????2000us???????????????????????????????? { SCL=0; Delay10us(); } } SCL=0; Delay10us(); } void I2cSendByte(unsigned char dat) { unsigned char a=0,b=0;//???255??????????????1us????????255us?? for(a=0;a<8;a++)//?????8λ???????λ??? { SDA=dat>>7; //?????????SCL=0??????????????SDA??? dat=dat<<1; Delay10us(); SCL=1; Delay10us();//???????>4.7us SCL=0; Delay10us();//??????4us } SDA=1; Delay10us(); SCL=0; Delay10us(); } unsigned char I2cReadByte() { unsigned char a=0,dat=0; SDA=1; //?????????????????SCL????0 Delay10us(); for(a=0;a<8;a++)//????8????? { SCL=1; Delay10us(); dat<<=1; dat|=SDA; Delay10us(); SCL=0; Delay10us(); } return dat; } void write_add(unsigned char addr,unsigned char dat) { I2cStart(); I2cSendByte(0xa0);//????д??????? respons(); I2cSendByte(addr);//?????д??????? respons(); I2cSendByte(dat); //???????? respons(); I2cStop(); } unsigned char read_add(unsigned char addr) { unsigned char num; I2cStart(); I2cSendByte(0xa0); //????д??????? respons(); I2cSendByte(addr); //???????????? respons(); I2cStart(); I2cSendByte(0xa1); //???????????? respons(); num=I2cReadByte(); //??????? I2cStop(); return num; } void init24c02() { SDA=1; Delay10us(); SCL=1; Delay10us(); miao=read_add(1); fen=read_add(2); shi=read_add(3); } void datapros() { disp[0]=shuju[miao%10]; disp[1]=shuju[miao/10]; disp[2]=shuju[fen%10]; disp[3]=shuju[fen/10]; disp[4]=shuju[shi%10]; disp[5]=shuju[shi/10]; } void display() { ui i; for(i=0;i<6;i++) { switch(i) { case(0): lsa=0;lsb=0;lsc=0;break; case(1): lsa=1;lsb=0;lsc=0;break; case(2): lsa=0;lsb=1;lsc=0;break; case(3): lsa=1;lsb=1;lsc=0;break; case(4): lsa=0;lsb=0;lsc=1;break; case(5): lsa=1;lsb=0;lsc=1;break; } P0=disp[i]; delay(100); P0=0x00; } } void init() { TMOD=0x01; TH0=0xfc; TL0=0x18; //1ms EA=1; TR0=1; ET0=1; } void key() { if(k1==0) { delay(100); { if(k1==0) { ss=ss+2; while(!k1); switch(ss) { case(2): lsa=0;lsb=0;lsc=0;TR0=0;break; case(4): lsa=0;lsb=1;lsc=0;break; case(6): lsa=0;lsb=0;lsc=1;break; case(8): ss=0;TR0=1;break; } } } } if(ss!=0) { if(k2==0) { delay(100); { if(k2==0) { while(!k2); if(ss==2) { miao++; if(miao==60) miao=0; write_add(1,miao); } if(ss==4) { fen++; if(fen==60) fen=0; write_add(2,fen); } if(ss==6) { shi++; if(shi==24) shi=0; write_add(3,shi); } } } } if(k3==0) { delay(100); if(k3==0) { while(!k3); if(ss==2) { miao--; if(miao==-1) miao=59; write_add(1,miao); } if(ss==4) { fen--; if(fen==-1) fen=59; write_add(2,fen); } if(ss==6) { shi--; if(shi==-1) shi=23; write_add(3,shi); } } } } } void main() { init(); init24c02(); while(1) { key(); datapros(); display(); } } void init0() interrupt 1 { TH0=0xfc; TL0=0x18; num++; if(num==1000) { miao++; num=0; if(miao==60) { miao=0; fen++; if(fen==60) { fen=0; shi++; if(shi==24) { shi=0; write_add(3,shi); } write_add(2,fen); } write_add(1,miao); } } }

单片机课程设计数字音乐盒

求一个关于51单片机数字音乐盒的课设,要求用的是汇编语言,尽量代码解释清楚

51单片机多功能时钟程序 LCD显示温度,实物显示不了。

实物LCD1602显示温度为0,其他信息正常显示,仿真一切正常,若将显示温度的函数单独提取成文件,则正常显示温度,不知道怎么改 PS只需看主函数,LCD1602.h和temp.h就行 ``` #include"key.h" #include"lcd1602.h" #include"ds1302.h" #include"naozhong.h" #include"temp.h" #include"nongli.h" #include "intrins.h" #define uchar unsigned char #define uint unsigned int uchar flag_nl,temperature; /*在LCD1602的坐标(x, y)位置显示星期*/ void LcdShowWeek(uchar x, uchar y, uchar dat) { uchar addr; if (y == 0) { addr = 0x00 + x; //第一行的x位置显示 } else { addr = 0x40 + x; //第二行x的位置显示 } LCD1602WriteCmd(addr + 0x80); switch(dat) { case 1:LCD1602WriteData('M');//星期数为1时,显示 LCD1602WriteData('O'); LCD1602WriteData('N'); break; case 2:LCD1602WriteData('T');//星期数据为2时显示 LCD1602WriteData('U'); LCD1602WriteData('E'); break; case 3:LCD1602WriteData('W');//星期数据为3时显示 LCD1602WriteData('E'); LCD1602WriteData('D'); break; case 4:LCD1602WriteData('T');//星期数据为4是显示 LCD1602WriteData('H'); LCD1602WriteData('U'); break; case 5:LCD1602WriteData('F');//星期数据为5时显示 LCD1602WriteData('R'); LCD1602WriteData('I'); break; case 6:LCD1602WriteData('S');//星期数据为6时显示 LCD1602WriteData('T'); LCD1602WriteData('A'); break; case 7:LCD1602WriteData('S');//星期数据为7时显示 LCD1602WriteData('U'); LCD1602WriteData('N'); break; } } /*显示温度*/ void LcdTimeDisplay(int temp) //lcd显示 { unsigned char datas[]={0,0}; //定义数组,室温比较小,所以只显示两位温度 float tp; if(temp< 0) //当温度值为负数 { LCD1602WriteCmd(0x80+0x0c); //写地址 LCD1602WriteData('-'); temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; } else { LCD1602WriteCmd(0x80+0x0c); //写地址 LCD1602WriteData('+'); tp=temp; temp=tp*0.0625*100+0.5; } datas[0] = temp / 10000; datas[1] = temp % 10000 / 1000; datas[2] = temp % 1000 / 100; datas[3] = temp % 100 / 10; datas[4] = temp % 10; LCD1602WriteCmd(0x8d); //写地址 LCD1602WriteData('0'+datas[1]); //十位 Delay_nms(1); LCD1602WriteCmd(0x8e); //写地址 LCD1602WriteData('0'+datas[2]); //个位 Delay_nms(1); } /*初始化计时器*/ void Timer0Init() { EA = 1; //开总中断 TMOD = 0X01; //定时器0、工作方式1 ET0 = 1; //开定时器0中断 TR0 = 1; //允许定时器0定时 } /*读取DS1302中的时间*/ void Ds1302ReadTime() { miao = Ds1302Read(READ_RTC_ADDR[0]); //读秒 fen = Ds1302Read(READ_RTC_ADDR[1]); //读分 shi = Ds1302Read(READ_RTC_ADDR[2]); //读时 ri = Ds1302Read(READ_RTC_ADDR[3]); //读日 yue = Ds1302Read(READ_RTC_ADDR[4]); //读月 week = Ds1302Read(READ_RTC_ADDR[5]); //读星期 nian = Ds1302Read(READ_RTC_ADDR[6]); //读年 Conversion(0,nian,yue,ri); //农历转换 n_nian = year_moon ; n_yue = month_moon ; n_ri = day_moon ; } void DS1302ShowPart() //LCD显示时间、温度 { LcdShowWeek(12,1,week); LcdShowNum(2,1,shi); LcdShowNum(5,1,fen); LcdShowNum(8,1,miao); if(flag_nl == 0) //显示阳历 { LcdShowNum(2,0,nian); LcdShowNum(5,0,yue); LcdShowNum(8,0,ri); } else { LcdShowNum(2,0,n_nian); LcdShowNum(5,0,n_yue); LcdShowNum(8,0,n_ri); } } /*时钟+*/ void Inc_Time() { if(bit_flag == 1) //设置年 { nian+=0x01; if((nian & 0x0f) >= 0x0a) nian = (nian & 0xf0) + 0x10; if(nian >= 0x9a) nian = 1; } if(bit_flag == 2) //设置月 { yue+=0x01; if((yue & 0x0f) >= 0x0a) yue = (yue & 0xf0) + 0x10; if(yue >= 0x13) yue = 1; } if(bit_flag == 3) //设置日 { ri+=0x01; if((ri & 0x0f) >= 0x0a) ri = (ri & 0xf0) + 0x10; if(ri >= 0x32) ri = 0; } if(bit_flag == 4) //设置星期 { week+=0x01; if((week & 0x0f) >= 0x0a) week = (week & 0xf0) + 0x10; if(week >= 0x08) week = 1; } if(bit_flag == 5) //设置时 { shi+=0x01; if((shi & 0x0f) >= 0x0a) shi = (shi & 0xf0) + 0x10; ///***shi & 0xf0低四位清零,(shi & 0xf0) + 0x10向高位进1(高四位加1)***/// if(shi >= 0x24) shi = 0; } if(bit_flag == 6) //设置分 { fen+=0x01; if((fen & 0x0f) >= 0x0a) fen = (fen & 0xf0) + 0x10; if(fen >= 0x60) fen = 0; } if(bit_flag == 7) //设置秒 { miao+=0x01; if((miao & 0x0f) >= 0x0a) miao = (miao & 0xf0) + 0x10; if(miao >= 0x60) miao = 0; } } /*时钟-*/ void Dec_Time() { if(bit_flag == 1) { if(nian == 0x01) nian = 0x9a; if((nian & 0x0f) == 0x00) nian = (nian | 0x0a) - 0x10; nian -- ; } if(bit_flag == 2) { if(yue == 0x01) yue = 0x13; if((yue & 0x0f) == 0x00) yue = (yue | 0x0a) - 0x10; yue -- ; } if(bit_flag == 3) { if(ri == 0x01) ri = 0x32; if((ri & 0x0f) == 0x00) ri = (ri | 0x0a) - 0x10; ri -- ; } if(bit_flag == 4) //设置星期 { if(week == 0x01) week = 0x08; if((week & 0x0f) == 0x00) week = (week | 0x0a) - 0x10; week -- ; } if(bit_flag == 5) //设置时 { if(shi == 0x00) shi = 0x24; if((shi & 0x0f) == 0x00) shi = (shi | 0x0a) - 0x10; ///***如果个位为0,高四位减1***/// shi -- ; } if(bit_flag == 6) //设置分 { if(fen == 0x00) fen = 0x5a; if((fen & 0x0f) == 0x00) fen = (fen | 0x0a) - 0x10; fen -- ; } if(bit_flag == 7) { if(miao == 0x00) miao = 0x5a; if((miao & 0x0f) == 0x00) miao = (miao | 0x0a) - 0x10; miao -- ; } } /*具体按键功能*/ void KeyAction() { if (KeyValue == 1) { mode_flag++; if(mode_flag == 1) // 设置时钟 { bit_flag=1; //设置位为年的十位 LcdShowStr(0,0,"20 - - C"); LcdShowStr(0,1," : : "); } if(mode_flag == 2) //设置闹钟 { bit_flag = 1; //设置位为时的十位 LcdShowStr(0,0," set alarm "); LcdShowStr(0,1,"ON "); } if(mode_flag > 2) //回到正常显示 { mode_flag = 0; bit_flag = 0; write_guangbiao(2,0,0); //关闭光标 Int_1602_Dis(); //初始化液晶显示 } } if(KeyValue == 2) //选择键 { flag_200ms = 1; if(mode_flag == 1) //设置时间 { bit_flag ++; //设置位右移 if(bit_flag > 7) bit_flag= 1; } if(mode_flag == 2) //设置闹钟 { bit_flag ++; if(bit_flag > 5) bit_flag = 1; } } if(mode_flag == 1) { if(KeyValue == 3) //加 { Inc_Time(); } if(KeyValue == 4) //减 { Dec_Time(); } LcdShowNum(2,0,nian); //显示时间 LcdShowNum(5,0,yue); LcdShowNum(8,0,ri); LcdShowWeek(12,1,week); LcdShowNum(2,1,shi); LcdShowNum(5,1,fen); LcdShowNum(8,1,miao); LcdTimeDisplay(temperature); switch(bit_flag) // 光标显示 { case 1: write_guangbiao(2,0,1); break; case 2: write_guangbiao(5,0,1); break; case 3: write_guangbiao(8,0,1); break; case 4: write_guangbiao(12,1,1); break; case 5: write_guangbiao(2,1,1); break; case 6: write_guangbiao(5,1,1); break; case 7: write_guangbiao(8,1,1); break; } SetTimetoDS1302(); } /***************设置闹钟*********************/ if(mode_flag == 2) { if(bit_flag == 1) //设置闹钟开关 { if(KeyValue == 3) { alarm_open = 1; //闹钟功能开 } if(KeyValue == 4) { alarm_open = 0; //闹钟功能关 } } if(alarm_open == 1) { LcdShowStr(0,1,"ON "); } else { LcdShowStr(0,1,"OFF"); } if(bit_flag == 2) //设置第一个闹钟时 { if(KeyValue == 3) //加 { shi1+=0x01; if((shi1 & 0x0f) >= 0x0a) shi1 = (shi1 & 0xf0) + 0x10; if(shi1 >= 0x24) shi1 = 0; } if(KeyValue == 4) //减 { if(shi1 == 0x00) shi1 = 0x5a; if((shi1 & 0x0f) == 0x00) shi1 = (shi1 | 0x0a) - 0x10; shi1 -- ; } } if(bit_flag == 3) //设置第一个闹钟分 { if(KeyValue == 3) //加 { fen1+=0x01; if((fen1 & 0x0f) >= 0x0a) fen1 = (fen1 & 0xf0) + 0x10; if(fen1 >= 0x60) fen1 = 0; } if(KeyValue == 4) //减 { if(fen1 == 0x00) fen1 = 0x5a; if((fen1 & 0x0f) == 0x00) fen1 = (fen1 | 0x0a) - 0x10; fen1 -- ; } } if(bit_flag == 4) //设置第二个闹钟时 { if(KeyValue == 3) //加 { shi2+=0x01; if((shi2 & 0x0f) >= 0x0a) shi2 = (shi2 & 0xf0) + 0x10; if(shi2 >= 0x24) shi2 = 0; } if(KeyValue == 4) //减 { if(shi2 == 0x00) shi2 = 0x5a; if((shi2 & 0x0f) == 0x00) shi2 = (shi2 | 0x0a) - 0x10; shi2 -- ; } } if(bit_flag == 5) //设置第二个闹钟分 { if(KeyValue == 3) //加 { fen2+=0x01; if((fen2 & 0x0f) >= 0x0a) fen2 = (fen2 & 0xf0) + 0x10; if(fen2 >= 0x60) fen2 = 0; } if(KeyValue == 4) //减 { if(fen2 == 0x00) fen2 = 0x5a; if((fen2 & 0x0f) == 0x00) fen2 = (fen2 | 0x0a) - 0x10; fen2 -- ; } } LcdShowNum(4,1,shi1); LcdShowNum(7,1,fen1); LcdShowNum(10,1,shi2); LcdShowNum(13,1,fen2); switch(bit_flag) // 光标显示 { case 1: write_guangbiao(0,1,1); break; case 2: write_guangbiao(4,1,1); break; case 3: write_guangbiao(7,1,1); break; case 4: write_guangbiao(10,1,1); break; case 5: write_guangbiao(13,1,1); break; } } } void main() { InitLCD1602(); InitDS1302(); Timer0Init(); //初始化定时器 Int_1602_Dis(); Delay_nms(500); while(1) { KeyDown(); if(KeyValue<10) { if(beep_flag ==0) //闹钟不响的状态下可以设置 { KeyAction(); } else { beep_flag= 0; //按下任意键可关闭闹钟 beep = 1; Ds1302ReadTime(); } if(mode_flag == 0) { if(KeyValue == 4) { flag_nl = ~flag_nl; //切换农历和阳历的显示标志位 if(flag_nl == 1) LcdShowStr(0,0,"N "); } } } if(mode_flag == 0) { Ds1302ReadTime(); //读时间 DS1302ShowPart(); LcdTimeDisplay(Ds18b20ReadTemp()); } naozhong_alarm(); //闹钟报警函数 Delay_nms(1); } } /**************定时器0中断程序*****************/ void Timer0() interrupt 1 { static uchar value; TH0 = 0X3C; TL0 = 0XB0; //50ms value ++; if((value % 2) == 0) //100ms flag_100ms = 1; } /****************************************************************/ #ifndef _temp_H_ #define _temp_H_ #include <reg51.h> //---重定义关键词---// #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif uchar temp; //--定义使用的IO口--// sbit DSPORT=P3^7; /******************************************************************************* * 函 数 名 : Delay1ms * 函数功能 : 延时函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Delay1ms(uint y) { uint x; for( ; y>0; y--) { for(x=110; x>0; x--); } } /******************************************************************************* * 函数名 : Ds18b20Init * 函数功能 : 初始化 * 输入 : 无 * 输出 : 初始化成功返回1,失败返回0 *******************************************************************************/ unsigned char Ds18b20Init() { unsigned int i; DSPORT=0; //将总线拉低480us~960us i=70; while(i--);//延时642us DSPORT=1; //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低 i=0; while(DSPORT) //等待DS18B20拉低总线 { i++; if(i>5000)//等待>5MS return 0;//初始化失败 } return 1;//初始化成功 } /******************************************************************************* * 函数名 : Ds18b20WriteByte * 函数功能 : 向18B20写入一个字节 * 输入 : com * 输出 : 无 *******************************************************************************/ void Ds18b20WriteByte(unsigned char dat) { unsigned int i,j; for(j=0;j<8;j++) { DSPORT=0; //每写入一位数据之前先把总线拉低1us i++; DSPORT=dat&0x01; //然后写入一个数据,从最低位开始 i=6; while(i--); //延时68us,持续时间最少60us DSPORT=1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值 dat>>=1; } } /******************************************************************************* * 函数名 : Ds18b20ReadByte * 函数功能 : 读取一个字节 * 输入 : com * 输出 : 无 *******************************************************************************/ unsigned char Ds18b20ReadByte() { unsigned char byte,bi; unsigned int i,j; for(j=8;j>0;j--) { DSPORT=0;//先将总线拉低1us i++; DSPORT=1;//然后释放总线 i++; i++;//延时6us等待数据稳定 bi=DSPORT; //读取数据,从最低位开始读取 /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/ byte=(byte>>1)|(bi<<7); i=4; //读取完之后等待48us再接着读取下一个数 while(i--); } return byte; } /******************************************************************************* * 函数名 : Ds18b20ChangTemp * 函数功能 : 让18b20开始转换温度 * 输入 : com * 输出 : 无 *******************************************************************************/ void Ds18b20ChangTemp() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0x44); //温度转换命令 // Delay1ms(100); //等待转换成功,而如果你是一直刷着的话,就不用这个延时了 } /******************************************************************************* * 函数名 : Ds18b20ReadTempCom * 函数功能 : 发送读取温度命令 * 输入 : com * 输出 : 无 *******************************************************************************/ void Ds18b20ReadTempCom() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0xbe); //发送读取温度命令 } /******************************************************************************* * 函数名 : Ds18b20ReadTemp * 函数功能 : 读取温度 * 输入 : com * 输出 : 无 *******************************************************************************/ int Ds18b20ReadTemp() { int temp=0; unsigned char tmh,tml; Ds18b20ChangTemp(); //先写入转换命令 Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令 tml=Ds18b20ReadByte(); //读取温度值共16位,先读低字节 tmh=Ds18b20ReadByte(); //再读高字节 temp=tmh; temp<<=8; temp|=tml; return temp; } #endif /************************************************************************/ #ifndef _lcd1602_H_ #define _lcd1602_H_ #include<reg51.h> #define LCD1602_DB P0 #define uchar unsigned char #define uint unsigned int #define LCD1602_4PINS //引脚定义 sbit LCD1602_RS = P2^6; sbit LCD1602_RW = P2^5; sbit LCD1602_EN = P2^7; uchar code table_num[]="0123456789abcdefg"; /*延时函数,延时1ms*/ void Lcd1602_Delay1ms(uint c) //误差 0us { uchar a,b; for (; c>0; c--) { for (b=199;b>0;b--) { for(a=1;a>0;a--); } } } /*LCD1602写命令*/ void LCD1602WriteCmd(uchar cmd) { LCD1602_RS = 0; LCD1602_RW = 0; LCD1602_EN = 0; LCD1602_DB = cmd; Lcd1602_Delay1ms(1); //等待数据稳定 LCD1602_EN = 1;//高脉冲 Lcd1602_Delay1ms(5); //等待数据稳定 LCD1602_EN = 0;//关闭液晶输出 LCD1602_DB = cmd<<4; Lcd1602_Delay1ms(1); LCD1602_EN = 1;//高脉冲 Lcd1602_Delay1ms(5); //等待数据稳定 LCD1602_EN = 0;//关闭液晶输出 } void LCD1602WriteData(uchar dat) { LCD1602_RS = 1; LCD1602_RW = 0; LCD1602_EN = 0; LCD1602_DB = dat;//送入数据 Lcd1602_Delay1ms(1); LCD1602_EN = 1;//高脉冲 Lcd1602_Delay1ms(5); LCD1602_EN = 0;//关闭液晶输出 LCD1602_DB = dat<<4; Lcd1602_Delay1ms(1); LCD1602_EN = 1;//高脉冲 Lcd1602_Delay1ms(5); LCD1602_EN = 0;//关闭液晶输出 } /*液晶初始化*/ void InitLCD1602() { LCD1602WriteCmd(0x32); LCD1602WriteCmd(0x28); LCD1602WriteCmd(0x0C); //开显示不显示光标 LCD1602WriteCmd(0x06); //写入字符时字符指针++且光标++ LCD1602WriteCmd(0x01); //显示清屏 } /*在LCD1602的坐标(x, y)位置显示str*/ void LcdShowStr(uchar x, uchar y, uchar * str) { uchar addr; if (y == 0) { addr = 0x00 + x; //第一行的x位置显示 } else { addr = 0x40 + x; //第二行x的位置显示 } LCD1602WriteCmd(addr + 0x80); while (*str != '\0') { LCD1602WriteData(*str++); } } /*在LCD1602的坐标(x, y)位置显示十进制数*/ void LcdShowNum(uchar x, uchar y, uchar dat) { uchar addr; if (y == 0) { addr = 0x00 + x; //第一行的x位置显示 } else { addr = 0x40 + x; //第二行x的位置显示 } LCD1602WriteCmd(addr + 0x80); LCD1602WriteData(table_num[dat/16]); LCD1602WriteData(table_num[dat%16]); } /*光标控制函数*/ void write_guangbiao(uchar x,uchar y,uchar dat) { if(y==0) LCD1602WriteCmd(0x80+x); else LCD1602WriteCmd(0x80+0x40+x); if(dat == 1) LCD1602WriteCmd(0x0f); //显示光标并且闪烁 else LCD1602WriteCmd(0x0c); //关闭光标 } /*屏幕初始化函数*/ void Int_1602_Dis() { LcdShowStr(0,0,"20 - - C"); LcdShowStr(0,1," : : "); } #endif /**********************************************************/ #ifndef _naozhong_H_ #define _naozhong_H_ sbit beep=P1^5; unsigned char alarm_open; //闹钟功能标志 unsigned char fen1=0x00,shi1=0x00,fen2=0x00,shi2=0x00; //两个闹钟变量的定义 unsigned char beep_flag;//闹钟开关标志 bit flag_100ms; unsigned char alarm_open=0; /*************闹钟报警函数***************/ void naozhong_alarm() { static unsigned char t,r; if(flag_100ms == 1) //100ms执行一次 { flag_100ms = 0; if(alarm_open == 1) //如果闹钟打开 { if((miao == 0) && (fen == fen1) && (shi == shi1)) { beep_flag = 1; //有报警 打开蜂鸣器响的标志位 } if(((miao == 0) && (fen == fen2) && (shi == shi2))) { beep_flag = 1; //有报警 打开蜂鸣器响的标志位 } if(beep_flag == 1) //闹钟以被打开 { beep = ~beep; Delay_nms(10); r ++; if(r >= 10) { r = 0; t++; if(t >= 60) { t = 0; beep_flag = 0; beep = 1; } } } } } } #endif /******************************************************/ #ifndef _key_H_ #define _key_H_ #include <reg51.h> #define uchar unsigned char #define uint unsigned int uchar KeyValue; //用来存放读取到的键值 uchar mode_flag; //模式标志 uchar bit_flag; //位标志 bit flag_200ms; void Delay_nms(unsigned int c) //延时1ms { unsigned char a,b; for (; c>0; c--) { for (b=199;b>0;b--) { for(a=1;a>0;a--); } } } //判断按键是否按下 并得到键值 void KeyDown() { static uchar key_new; KeyValue = 20; //按键值还原 P3 |= 0xff; //对应的按键IO口输出为1 if((P3 & 0xff) != 0xff) //按键按下 { Delay_nms(1); //按键消抖动 if(((P3 & 0xff) != 0xff) && (key_new == 1)) { //确认是按键按下 key_new = 0; switch(P3 & 0xff) { case 0xfe: KeyValue = 4; break; //得到按键值 case 0xfd: KeyValue = 3; break; //得到按键值 case 0xfb: KeyValue = 2; break; //得到按键值 case 0xf7: KeyValue = 1; break; //得到按键值 } } } else key_new = 1; } #endif /**********************************************************************/ #ifndef _nongli_H_ #define _nongli_H_ #include <intrins.h> //公历年对应的农历数据,每年三字节, //格式第一字节BIT7-4 位表示闰月月份,值为0 为无闰月,BIT3-0 对应农历第1-4 月的大小 //第二字节BIT7-0 对应农历第5-12 月大小,第三字节BIT7 表示农历第13 个月大小 //月份对应的位为1 表示本农历月大(30 天),为0 表示小(29 天). //第三字节BIT6-5 表示春节的公历月份,BIT4-0 表示春节的公历日期 //********阳历转换阴历表************************************ code unsigned char year_code[597]={ 0x04,0xAe,0x53, //1901 0 0x0A,0x57,0x48, //1902 3 0x55,0x26,0xBd, //1903 6 0x0d,0x26,0x50, //1904 9 0x0d,0x95,0x44, //1905 12 0x46,0xAA,0xB9, //1906 15 0x05,0x6A,0x4d, //1907 18 0x09,0xAd,0x42, //1908 21 0x24,0xAe,0xB6, //1909 0x04,0xAe,0x4A, //1910 0x6A,0x4d,0xBe, //1911 0x0A,0x4d,0x52, //1912 0x0d,0x25,0x46, //1913 0x5d,0x52,0xBA, //1914 0x0B,0x54,0x4e, //1915 0x0d,0x6A,0x43, //1916 0x29,0x6d,0x37, //1917 0x09,0x5B,0x4B, //1918 0x74,0x9B,0xC1, //1919 0x04,0x97,0x54, //1920 0x0A,0x4B,0x48, //1921 0x5B,0x25,0xBC, //1922 0x06,0xA5,0x50, //1923 0x06,0xd4,0x45, //1924 0x4A,0xdA,0xB8, //1925 0x02,0xB6,0x4d, //1926 0x09,0x57,0x42, //1927 0x24,0x97,0xB7, //1928 0x04,0x97,0x4A, //1929 0x66,0x4B,0x3e, //1930 0x0d,0x4A,0x51, //1931 0x0e,0xA5,0x46, //1932 0x56,0xd4,0xBA, //1933 0x05,0xAd,0x4e, //1934 0x02,0xB6,0x44, //1935 0x39,0x37,0x38, //1936 0x09,0x2e,0x4B, //1937 0x7C,0x96,0xBf, //1938 0x0C,0x95,0x53, //1939 0x0d,0x4A,0x48, //1940 0x6d,0xA5,0x3B, //1941 0x0B,0x55,0x4f, //1942 0x05,0x6A,0x45, //1943 0x4A,0xAd,0xB9, //1944 0x02,0x5d,0x4d, //1945 0x09,0x2d,0x42, //1946 0x2C,0x95,0xB6, //1947 0x0A,0x95,0x4A, //1948 0x7B,0x4A,0xBd, //1949 0x06,0xCA,0x51, //1950 0x0B,0x55,0x46, //1951 0x55,0x5A,0xBB, //1952 0x04,0xdA,0x4e, //1953 0x0A,0x5B,0x43, //1954 0x35,0x2B,0xB8, //1955 0x05,0x2B,0x4C, //1956 0x8A,0x95,0x3f, //1957 0x0e,0x95,0x52, //1958 0x06,0xAA,0x48, //1959 0x7A,0xd5,0x3C, //1960 0x0A,0xB5,0x4f, //1961 0x04,0xB6,0x45, //1962 0x4A,0x57,0x39, //1963 0x0A,0x57,0x4d, //1964 0x05,0x26,0x42, //1965 0x3e,0x93,0x35, //1966 0x0d,0x95,0x49, //1967 0x75,0xAA,0xBe, //1968 0x05,0x6A,0x51, //1969 0x09,0x6d,0x46, //1970 0x54,0xAe,0xBB, //1971 0x04,0xAd,0x4f, //1972 0x0A,0x4d,0x43, //1973 0x4d,0x26,0xB7, //1974 0x0d,0x25,0x4B, //1975 0x8d,0x52,0xBf, //1976 0x0B,0x54,0x52, //1977 0x0B,0x6A,0x47, //1978 0x69,0x6d,0x3C, //1979 0x09,0x5B,0x50, //1980 0x04,0x9B,0x45, //1981 0x4A,0x4B,0xB9, //1982 0x0A,0x4B,0x4d, //1983 0xAB,0x25,0xC2, //1984 0x06,0xA5,0x54, //1985 0x06,0xd4,0x49, //1986 0x6A,0xdA,0x3d, //1987 0x0A,0xB6,0x51, //1988 0x09,0x37,0x46, //1989 0x54,0x97,0xBB, //1990 0x04,0x97,0x4f, //1991 0x06,0x4B,0x44, //1992 0x36,0xA5,0x37, //1993 0x0e,0xA5,0x4A, //1994 0x86,0xB2,0xBf, //1995 0x05,0xAC,0x53, //1996 0x0A,0xB6,0x47, //1997 0x59,0x36,0xBC, //1998 0x09,0x2e,0x50, //1999 294 0x0C,0x96,0x45, //2000 297 0x4d,0x4A,0xB8, //2001 0x0d,0x4A,0x4C, //2002 0x0d,0xA5,0x41, //2003 0x25,0xAA,0xB6, //2004 0x05,0x6A,0x49, //2005 0x7A,0xAd,0xBd, //2006 0x02,0x5d,0x52, //2007 0x09,0x2d,0x47, //2008 0x5C,0x95,0xBA, //2009 0x0A,0x95,0x4e, //2010 0x0B,0x4A,0x43, //2011 0x4B,0x55,0x37, //2012 0x0A,0xd5,0x4A, //2013 0x95,0x5A,0xBf, //2014 0x04,0xBA,0x53, //2015 0x0A,0x5B,0x48, //2016 0x65,0x2B,0xBC, //2017 0x05,0x2B,0x50, //2018 0x0A,0x93,0x45, //2019 0x47,0x4A,0xB9, //2020 0x06,0xAA,0x4C, //2021 0x0A,0xd5,0x41, //2022 0x24,0xdA,0xB6, //2023 0x04,0xB6,0x4A, //2024 0x69,0x57,0x3d, //2025 0x0A,0x4e,0x51, //2026 0x0d,0x26,0x46, //2027 0x5e,0x93,0x3A, //2028 0x0d,0x53,0x4d, //2029 0x05,0xAA,0x43, //2030 0x36,0xB5,0x37, //2031 0x09,0x6d,0x4B, //2032 0xB4,0xAe,0xBf, //2033 0x04,0xAd,0x53, //2034 0x0A,0x4d,0x48, //2035 0x6d,0x25,0xBC, //2036 0x0d,0x25,0x4f, //2037 0x0d,0x52,0x44, //2038 0x5d,0xAA,0x38, //2039 0x0B,0x5A,0x4C, //2040 0x05,0x6d,0x41, //2041 0x24,0xAd,0xB6, //2042 0x04,0x9B,0x4A, //2043 0x7A,0x4B,0xBe, //2044 0x0A,0x4B,0x51, //2045 0x0A,0xA5,0x46, //2046 0x5B,0x52,0xBA, //2047 0x06,0xd2,0x4e, //2048 0x0A,0xdA,0x42, //2049 0x35,0x5B,0x37, //2050 0x09,0x37,0x4B, //2051 0x84,0x97,0xC1, //2052 0x04,0x97,0x53, //2053 0x06,0x4B,0x48, //2054 0x66,0xA5,0x3C, //2055 0x0e,0xA5,0x4f, //2056 0x06,0xB2,0x44, //2057 0x4A,0xB6,0x38, //2058 0x0A,0xAe,0x4C, //2059 0x09,0x2e,0x42, //2060 0x3C,0x97,0x35, //2061 0x0C,0x96,0x49, //2062 0x7d,0x4A,0xBd, //2063 0x0d,0x4A,0x51, //2064 0x0d,0xA5,0x45, //2065 0x55,0xAA,0xBA, //2066 0x05,0x6A,0x4e, //2067 0x0A,0x6d,0x43, //2068 0x45,0x2e,0xB7, //2069 0x05,0x2d,0x4B, //2070 0x8A,0x95,0xBf, //2071 0x0A,0x95,0x53, //2072 0x0B,0x4A,0x47, //2073 0x6B,0x55,0x3B, //2074 0x0A,0xd5,0x4f, //2075 0x05,0x5A,0x45, //2076 0x4A,0x5d,0x38, //2077 0x0A,0x5B,0x4C, //2078 0x05,0x2B,0x42, //2079 0x3A,0x93,0xB6, //2080 0x06,0x93,0x49, //2081 0x77,0x29,0xBd, //2082 0x06,0xAA,0x51, //2083 0x0A,0xd5,0x46, //2084 0x54,0xdA,0xBA, //2085 0x04,0xB6,0x4e, //2086 0x0A,0x57,0x43, //2087 0x45,0x27,0x38, //2088 0x0d,0x26,0x4A, //2089 0x8e,0x93,0x3e, //2090 0x0d,0x52,0x52, //2091 0x0d,0xAA,0x47, //2092 0x66,0xB5,0x3B, //2093 0x05,0x6d,0x4f, //2094 0x04,0xAe,0x45, //2095 0x4A,0x4e,0xB9, //2096 0x0A,0x4d,0x4C, //2097 0x0d,0x15,0x41, //2098 0x2d,0x92,0xB5, //2099 }; ///月份数据表 code unsigned int day_code[12]={0x00,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3,0x111,0x130,0x14e}; bit c_moon; //世纪 unsigned char year_moon,month_moon,day_moon; //判断农历月的大月或小月,如果该月为大返回1,为小返回0 bit get_moon_day(unsigned char month_p,unsigned int table_addr) { unsigned char temp; switch (month_p){ case 1:{temp=year_code[table_addr]&0x08; if (temp==0)return(0);else return(1);} case 2:{temp=year_code[table_addr]&0x04; if (temp==0)return(0);else return(1);} case 3:{temp=year_code[table_addr]&0x02; if (temp==0)return(0);else return(1);} case 4:{temp=year_code[table_addr]&0x01; if (temp==0)return(0);else return(1);} case 5:{temp=year_code[table_addr+1]&0x80; if (temp==0) return(0);else return(1);} case 6:{temp=year_code[table_addr+1]&0x40; if (temp==0)return(0);else return(1);} case 7:{temp=year_code[table_addr+1]&0x20; if (temp==0)return(0);else return(1);} case 8:{temp=year_code[table_addr+1]&0x10; if (temp==0)return(0);else return(1);} case 9:{temp=year_code[table_addr+1]&0x08; if (temp==0)return(0);else return(1);} case 10:{temp=year_code[table_addr+1]&0x04; if (temp==0)return(0);else return(1);} case 11:{temp=year_code[table_addr+1]&0x02; if (temp==0)return(0);else return(1);} case 12:{temp=year_code[table_addr+1]&0x01; if (temp==0)return(0);else return(1);} case 13:{temp=year_code[table_addr+2]&0x80; if (temp==0)return(0);else return(1);} } return(0); } /* 函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年) 调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun) 如:计算2004年10月16日Conversion(0,0x4,0x10,0x16); c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世 纪,c_sun=1为19世纪 调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据 */ void Conversion(bit c,unsigned char year,unsigned char month,unsigned char day)//公历日期 { //c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据 unsigned char temp1,temp2,temp3,month_p; unsigned int temp4,table_addr; bit flag2,flag_y; temp1=year/16; //BCD->hex 先把数据转换为十六进制 temp2=year%16; year=temp1*10+temp2; temp1=month/16; temp2=month%16; month=temp1*10+temp2; temp1=day/16; temp2=day%16; day=temp1*10+temp2; //定位数据表地址 if(c==0){ table_addr=(year+0x64-1)*0x03; //19..年 } else { table_addr=(year-1)*0x03; } //取当年春节所在的公历月份 temp1=year_code[table_addr+2]&0x60; temp1=_cror_(temp1,5); //取当年春节所在的公历日 temp2=year_code[table_addr+2]&0x1f; // 计算当年春年离当年元旦的天数,春节只会在公历1月或2月 if(temp1==0x01){ temp3=temp2-1; } else{ temp3=temp2+0x1f-1; } // 计算当年春年离当年元旦的天数完成 //计算公历日离当年元旦的天数 temp4=day_code[month-1]+day-1; if ((year%0x04==0)||((year%0x64)&&(year%0x190))) //闰年 { if((month>0x02)) //月份超过2 temp4+=1; } //判断公历日在春节前还是春节后 if (temp4>=temp3) { //公历日在春节后或就是春节当日使用下面代码进行运算 temp4-=temp3; month=0x01; month_p=0x01; //month_p为农历月份指向,公历日在春节前或就是春节当日month_p指向首月 flag2=get_moon_day(month_p,table_addr); //检查该农历月为大小还是小月,大月返回1,小月返回0 flag_y=0; if(flag2==0) temp1=0x1d; //小月29天 else temp1=0x1e; //大月30天 temp2=year_code[table_addr]&0xf0; temp2=_cror_(temp2,4); //从数据表中取该年的闰月月份,如为0则该年无闰月 while(temp4>=temp1){ temp4-=temp1; month_p+=1; if(month==temp2) { flag_y=~flag_y; //闰了该月,月份数值不加 if(flag_y==0) month+=1; } else month+=1; flag2=get_moon_day(month_p,table_addr); if(flag2==0) temp1=0x1d; else temp1=0x1e; } day=temp4+1; } else { //公历日在春节前使用下面代码进行运算 temp3-=temp4; if (year==0x00) //是否在21世纪 {year=0x63;c=1;} else year-=1; table_addr-=0x03; month=0x0c; temp2=year_code[table_addr]&0xf0; //闰月月份 temp2=_cror_(temp2,4); if (temp2==0) //无闰月 month_p=0x0c; //指向12月 else month_p=0x0d; // 指向13月 //month_p为月份指向,如果当年有闰月,一年有十三个月,月指向13,无闰月指向12 flag_y=0; flag2=get_moon_day(month_p,table_addr); if(flag2==0) temp1=0x1d; else temp1=0x1e; while(temp3>temp1) { temp3-=temp1; month_p-=1; if(flag_y==0) month-=1; if(month==temp2) flag_y=~flag_y; flag2=get_moon_day(month_p,table_addr); if(flag2==0) temp1=0x1d; else temp1=0x1e; } day=temp1-temp3+1; } c_moon=c; //HEX->BCD ,运算结束后,把数据转换为BCD数据 temp1=year/10; temp1=_crol_(temp1,4); temp2=year%10; year_moon=temp1|temp2; temp1=month/10; temp1=_crol_(temp1,4); temp2=month%10; month_moon=temp1|temp2; temp1=day/10; temp1=_crol_(temp1,4); temp2=day%10; day_moon=temp1|temp2; } #endif ```

请问,多个按键消抖与检测

有15个按键,没个对应一个I/O口,怎么编写C程序,使得对按键识别的同时并消抖,谢谢大神了

51单片机矩阵键盘与八位共阴数码管问题求指点

目标是实现根据矩阵键盘输入内容显示对应的数字(0到f),如按下S1->S8会显示0->7八个数字,在上述情况下按下S9后会显示1->8八位数,再按下S10后会显示2->9;按S16清除数码管显示内容; 出现问题:当八位数码管都有数字时按下下一个按键后会覆盖最后一位,但第一位不会被移出显示屏;![图片说明](https://img-ask.csdn.net/upload/201703/28/1490663857_889903.jpg)![图片说明](https://img-ask.csdn.net/upload/201703/28/1490663880_521750.jpg)![图片说明](https://img-ask.csdn.net/upload/201703/28/1490663898_329589.jpg) ``` // 内容:如计算器输入数据形式相同 从右至左 使用行列扫描方法 ------------------------------------------------*/ #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 #include <intrins.h> #define KeyPort P2 sbit LATCH = P1^2; //SER 串行数据 sbit SRCLK= P1^1; //SCK 串行时钟信号 sbit SER = P1^0; //ST 锁存输出信号 unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};// 显示段码值0~F unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码 unsigned char TempData[10]; //存储显示值的全局变量 void DelayUs2x(unsigned char t);//us级延时函数声明 void DelayMs(unsigned char t); //ms级延时 void Display(unsigned char FirstBit,unsigned char Num);//数码管显示函数 unsigned char KeyScan(void);//键盘扫描 unsigned char KeyPro(void); void Init_Timer0(void);//定时器初始化 /*------------------------------------------------ 主函数 ------------------------------------------------*/ void main (void) { unsigned char num,i,j; unsigned char temp[8]; Init_Timer0(); while (1) //主循环 { num=KeyPro(); if(num!=0xff) { if(i<8) { temp[i]=dofly_DuanMa[num]; for(j=0;j<=i;j++) TempData[7-i+j]=temp[j]; } i++; if(i==8)//多出一个按键输入为了清屏 原本应该为8 { i=0; if(j==500) { j=0; num++; if(num==9) num=0; } } } } /*------------------------------------------------ uS延时函数,含有输入参数 unsigned char t,无返回值 unsigned char 是定义无符号字符变量,其值的范围是 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时 长度如下 T=tx2+5 uS ------------------------------------------------*/ void DelayUs2x(unsigned char t) { while(--t); } /*------------------------------------------------ mS延时函数,含有输入参数 unsigned char t,无返回值 unsigned char 是定义无符号字符变量,其值的范围是 0~255 这里使用晶振12M,精确延时请使用汇编 ------------------------------------------------*/ void DelayMs(unsigned char t) { while(t--) { //大致延时1mS DelayUs2x(245); DelayUs2x(245); } } /*------------------------------------------------ 发送字节程序 ------------------------------------------------*/ void hc595SendByte(unsigned char dat) { unsigned char i; for(i=0; i<8; i++) { SRCLK=0; SER=dat&0x80; dat<<=1; SRCLK=1; } } /*------------------------------------------------ 发送双字节程序 595级联,n个595,就需要发送n字节后锁存 ------------------------------------------------*/ void Send2Byte(unsigned char dat1,unsigned char dat2) { hc595SendByte(dat1); hc595SendByte(dat2); } /*------------------------------------------------ 595锁存程序 595级联发送数据后,锁存有效 ------------------------------------------------*/ void Out595(void) { LATCH=1; _nop_(); LATCH=0; } /*------------------------------------------------ 显示函数,用于动态扫描数码管 输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示 如输入0表示从第一个显示。 Num表示需要显示的位数,如需要显示99两位数值则该值输入2 ------------------------------------------------*/ void Display(unsigned char FirstBit,unsigned char Num) { static unsigned char i=0; Send2Byte(dofly_WeiMa[i+FirstBit],TempData[i]); Out595(); i++; if(i==Num) i=0; } /*------------------------------------------------ 定时器初始化子程序 ------------------------------------------------*/ void Init_Timer0(void) { TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 //TH0=0x00; //给定初值 //TL0=0x00; EA=1; //总中断打开 ET0=1; //定时器中断打开 TR0=1; //定时器开关打开 } /*------------------------------------------------ 定时器中断子程序 ------------------------------------------------*/ void Timer0_isr(void) interrupt 1 { TH0=(65536-2000)/256; //重新赋值 2ms TL0=(65536-2000)%256; Display(0,8); // 调用数码管扫描 } /*------------------------------------------------ 按键扫描函数,返回扫描键值 ------------------------------------------------*/ unsigned char KeyScan(void) //键盘扫描函数,使用行列逐级扫描法 { unsigned char Val; KeyPort=0xf0;//高四位置高,低四位拉低 if(KeyPort!=0xf0)//表示有按键按下 { DelayMs(10); //去抖 if(KeyPort!=0xf0) { //表示有按键按下 KeyPort=0xfe; //检测第一行 if(KeyPort!=0xfe) { Val=KeyPort&0xf0; Val+=0x0e; while(KeyPort!=0xfe); DelayMs(10); //去抖 while(KeyPort!=0xfe); return Val; } KeyPort=0xfd; //检测第二行 if(KeyPort!=0xfd) { Val=KeyPort&0xf0; Val+=0x0d; while(KeyPort!=0xfd); DelayMs(10); //去抖 while(KeyPort!=0xfd); return Val; } KeyPort=0xfb; //检测第三行 if(KeyPort!=0xfb) { Val=KeyPort&0xf0; Val+=0x0b; while(KeyPort!=0xfb); DelayMs(10); //去抖 while(KeyPort!=0xfb); return Val; } KeyPort=0xf7; //检测第四行 if(KeyPort!=0xf7) { Val=KeyPort&0xf0; Val+=0x07; while(KeyPort!=0xf7); DelayMs(10); //去抖 while(KeyPort!=0xf7); return Val; } } } return 0xff; } /*------------------------------------------------ 按键值处理函数,返回扫键值 ------------------------------------------------*/ unsigned char KeyPro(void) { switch(KeyScan()) { case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值 case 0x7d:return 1;break;//1 case 0x7b:return 2;break;//2 case 0x77:return 3;break;//3 case 0xbe:return 4;break;//4 case 0xbd:return 5;break;//5 case 0xbb:return 6;break;//6 case 0xb7:return 7;break;//7 case 0xde:return 8;break;//8 case 0xdd:return 9;break;//9 case 0xdb:return 10;break;//a case 0xd7:return 11;break;//b case 0xee:return 12;break;//c case 0xed:return 13;break;//d case 0xeb:return 14;break;//e case 0xe7:return 15;break;//f default:return 0xff;break; } } ```

51单片机十字路口交通灯设计 求问

明天就要课设答辩了 影响着自己毕业。求大神帮我讲解一下这个程序 谢谢了 ``` #include <reg51.h> #include<absacc.h> #define COM XBYTE[0xCFE9] #define DAT XBYTE[0xCFE8] void Init_8279(void); void led_display(void); void Key_Scan(void); void key_action(void); void led_init_status(void); void delay(void); unsigned char led_buf[8]; //数码管显示缓冲数组 unsigned char KeyVal = 0x00; //当前按键的键值 unsigned char led_char[17] = { //数码管数字真值表 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71, }; sbit R_LED1 = P1^0; sbit G_LED1 = P1^1; sbit Y_LED1 = P1^2; sbit Y_LED3 = P1^3; sbit R_LED2 = P1^4; sbit G_LED2 = P1^5; sbit Y_LED2 = P1^6; sbit Y_LED4 = P1^7; int main(void) { TMOD = 0x01; //定时器模式设置 TH0 = 0xfc; TL0 = 0x18; TR0 = 1; EA = 1; //总中断使能 ET0 = 1; //定时器中断0使能 Init_8279(); while(1) { Key_Scan(); //按键扫描函数 } } void Init_8279(void) { COM = 0xd1; //总清除命令 do { ACC = COM; } //读取8279状态 while(ACC^7 == 1); //等待清除结束 COM = 0x00; //8个字符显示,左入口;,双键锁定 COM = 0x2a; //时钟分频 } //数码管显示函数,实现数码管动态扫描 void led_display(void) { static unsigned char j = 0; //静态局部变量,只初始化一次, COM = 0x82 + j; //发送显示地址,0x80为左一,程序里0x80,0x81数码管未使用,j = 0时,显示0x82位置的数码管,j=1时83,。。。 DAT = led_buf[j]; //依次把缓冲数组的内容显示 j++; if(j >= 4) //四个数码管 j = 0; } //按键扫描函数, 主循环调用 void Key_Scan(void) { unsigned char temp = 0; while((temp & 0x0f) == 0) //没有检测到按键程序停在这里,中断服务函数负责完成其他工作 { temp = COM; } //能执行到此处说明检测到了按键 COM = 0x40; //读按键值命令 KeyVal = DAT; //取键值 KeyVal &= 0x0f; //取低4位 KeyVal += 1; //因为按下第一个按键时,得到的键值位0x00,加一为了后面方便操作 key_action(); //检测到按键,并执行相应动作 } unsigned long sec_1s = 0; //全局时间,赋值多少当前秒是多少 unsigned char xingren = 0; unsigned char sec_1s_bak = 0; unsigned char bianhuan = 40; void key_action(void) {if(KeyVal == 0x01) {xingren = 1; sec_1s_bak = sec_1s; sec_1s = 0; } if(KeyVal == 0x02) {bianhuan = 40; sec_1s = 0; } if(KeyVal == 0x03) {bianhuan = 20; sec_1s = 0; } if(KeyVal == 0x04) {bianhuan = 10; sec_1s = 0; } } unsigned long ms2 = 0; //2ms计数 bit dir = 1; void InterruptTimer0() interrupt 1 { TH0 = 0xfc; //重新装在定时器的值 TL0 = 0x18; ms2++; //进来一次表示2ms if(ms2 >= 500) //累计500次则表示1s { ms2 = 0; //归零 sec_1s++; //1s计数器 加一 if(xingren == 1) { R_LED1 = 0; G_LED1 = 1; Y_LED1 = 1; Y_LED3 = 1; R_LED2 = 0; G_LED2 = 1; Y_LED2 = 1; Y_LED4 = 1; led_buf[2] = led_char[0]; led_buf[3] = led_char[10 - sec_1s]; if(sec_1s == 9) { xingren = 0; P1 = 0XFF; sec_1s = sec_1s_bak; } } else if(sec_1s >= 0 && sec_1s <= bianhuan) { if(dir) { R_LED1 = 0; G_LED2 = 0; } else { R_LED2 = 0; G_LED1 = 0; } led_buf[2] = led_char[(bianhuan + 1 - sec_1s)/10]; led_buf[3] = led_char[(bianhuan + 1 - sec_1s)%10]; } else if(sec_1s >= bianhuan && sec_1s <= bianhuan + 4) { R_LED1 = 1; G_LED1 = 1; Y_LED1 = 0; Y_LED3 = 0; R_LED2 = 1; G_LED2 = 1; Y_LED2 = 0; Y_LED4 = 0; led_buf[0] = led_char[0]; led_buf[1] = led_char[4 - sec_1s%10]; if(sec_1s == bianhuan + 4) { sec_1s = 0; dir = ~dir; Y_LED1 = 1; Y_LED3 = 1; Y_LED2 = 1; Y_LED4 = 1; } } } led_display(); //刷新数码管显示,放在中断中保证及时刷新显示 } ```

矩阵键盘按键输入多位数的显示问题

是这样的,矩阵键盘那一部分已经完成了,就是显示这一块,比如想通过键盘输入125,先按1,应该显示001;再按2,显示012;最后按5,显示125。但是问题是先后分别显示的是111、222、555。显示部分的代码如下: 数码管显示部分的时钟是1KHZ; key_data=4'hb或4'hc或4'ha是我定义的功能键; 按理key_data_reg0、key_data_reg1、key_data_reg2、key_data_reg3的变化应该如下: 按下c键(设置按键):key_data_reg0=0 key_data_reg1=0 key_data_reg2=0 key_data_reg3=0 按下1键: key_data_reg0=1 key_data_reg1=0 key_data_reg2=0 key_data_reg3=0 按下2键: key_data_reg0=2 key_data_reg1=1 key_data_reg2=0 key_data_reg3=0 按下5键: key_data_reg0=5 key_data_reg1=2 key_data_reg2=1 key_data_reg3=0 按下a键(确认按键):key_data_reg0=a key_data_reg1=5 key_data_reg2=2 key_data_reg3=1 ``` module display( clk , rst_n , key_data , sel , seg ); //输入信号定义 input clk ; input rst_n ; input[3:0] key_data ; //输出信号定义 output sel ; output seg ; //输出信号reg定义 reg[2:0] sel ; //数码管的位选信号 reg[7:0] seg ; //数码段的段选信号 //中间信号定义 reg[3:0] disp_data ; //单个数码管要显示的数据 reg[3:0] key_data_reg0 ; reg[3:0] key_data_reg1 ; reg[3:0] key_data_reg2 ; reg[3:0] key_data_reg3 ; always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin sel <= 3'b110; end else if(sel == 3'b110)begin sel <= 3'b101; end else if(sel == 3'b101)begin sel <= 3'b011; end else begin sel <= 3'b110; end end always@(key_data)begin if(rst_n==1'b0)begin key_data_reg0 <= 4'd0; key_data_reg1 <= 4'd0; key_data_reg2 <= 4'd0; key_data_reg3 <= 4'd0; end else if(key_data == 4'hb | key_data == 4'hc)begin key_data_reg0 <= 4'd0; key_data_reg1 <= 4'd0; key_data_reg2 <= 4'd0; key_data_reg3 <= 4'd0; end else begin key_data_reg0 <= key_data; key_data_reg1 <= key_data_reg0; key_data_reg2 <= key_data_reg1; key_data_reg3 <= key_data_reg2; end end always @(posedge clk or negedge rst_n)begin //将对应位数的值赋给对应位数码管 case(sel) 3'b110: disp_data <= key_data_reg1 ; 3'b101: disp_data <= key_data_reg2 ; 3'b011: disp_data <= key_data_reg3; default: disp_data <= 4'b0000; endcase end always @(posedge clk or negedge rst_n)begin //数码管显示表 if(rst_n == 1'b0)begin seg = 8'b11000000; end else begin case(disp_data) 4'd0:seg = 8'b11000000; 4'd1:seg = 8'b11111001; 4'd2:seg = 8'b10100100; 4'd3:seg = 8'b10110000; 4'd4:seg = 8'b10011001; 4'd5:seg = 8'b10010010; 4'd6:seg = 8'b10000010; 4'd7:seg = 8'b11111000; 4'd8:seg = 8'b10000000; 4'd9:seg = 8'b10010000; default:seg = 8'b10001110; endcase end end endmodule ``` 单纯的对这段代码进行了仿真,如图结果应该是正确的,但是到板子上就不对了。 怀疑是时序问题,但是对时序问题不知如何下手(可能实际按键输入值key_data与我仿真时给key_data直接赋值不一样?) 又或者是阻塞非阻塞的问题?

单片机设计电子秒表at89c51 求仿真原理图

利用单片机的定时器/计数器定时和计数,并使用LED数码管显示计时的时间来制作一 个电子秒表。 设计要求 (1)能够多次计时; (2)能够查询计时时间

基于AT89C51和LCD1602的电子时钟

![图片说明](https://img-ask.csdn.net/upload/202006/09/1591690883_991194.png) 要求: 在第2行显示当前时间,可用按键调整时,分。 keil编程 可以帮我用c语言写一下代码吗?

实现STC实时时钟的闹钟

如何用定时中断来实现在一个可设置时间上响铃,比如设置9点十分到了,蜂鸣器自动响

51单片机数码管动态显示的问题

我想比如在数码管输出5201314的话,采用动态刷新,用delay函数,但是现在发现一个问题,我把delay的时间设置的越短越不抖动,但为什么不加delay却显示不对了呢?我认为不加delay就是delay的时间无限短,那不应该显示的更清楚更不抖动么?好疑惑 #include<reg52.h> sbit duan=P2^6; sbit wei=P2^7; //#define a 200 void delay(unsigned int i) { while(--i); } void main() { while(1) { P0=0xfe; wei=1; wei=0; P0=0x6D; duan=1; duan=0; //delay(a); P0=0xfd; wei=1; wei=0; P0=0x5B; duan=1; duan=0; //delay(a); P0=0xfb; wei=1; wei=0; P0=0x3f; duan=1; duan=0; //delay(a); P0=0xf7; wei=1; wei=0; P0=0x06; duan=1; duan=0; //delay(a); P0=0xef; wei=1; wei=0; P0=0x4f; duan=1; duan=0; //delay(a); P0=0xdf; wei=1; wei=0; P0=0x06; duan=1; duan=0; //delay(a); P0=0xbf; wei=1; wei=0; P0=0x66; duan=1; duan=0; //delay(a); } }

C51单片机程控滤波器的程序

#include <reg52.h> #include "i2c.h" #include "delay.h" #include "display.h" #include "key.h" #define AddWr 0x90 #define AddRd 0x91 sbit P00=P0^0; sbit P01=P0^1; sbit P02=P0^2; sbit P03=P0^3; sbit P04=P0^4; extern bit ack; unsigned char ReadADC(unsigned char Chl); /*------------------------------------------------ 读AD转值程序 输入参数 Chl 表示需要转换的通道,范围从0-3 返回值范围0-255 ------------------------------------------------*/ unsigned char ReadADC(unsigned char Chl) { unsigned char Val; Start_I2c(); SendByte(AddWr); if(ack==0)return(0); SendByte(0x40|Chl); if(ack==0)return(0); Start_I2c(); SendByte(AddWr+1); if(ack==0)return(0); Val=RcvByte(); NoAck_I2c(); Stop_I2c(); return(Val); } /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { unsigned char Chl; unsigned char num=0; P35=0; Init_Timer0(); P3 = 0x0F; //按键初始化 0000 1111 while (1) //主循环 { KeyScan(); /*按键控制电压输出0~2V变化 并在数码管上显示*/ DelayMs(100); Display(0,4); num=ReadADC(0);/*AD转换 I/O口输出实时电压变化*/ DelayMs(100); ShowData(ReadADC(Chl),TempData); Display(0,4); P00=SetDACOut(ReadADC(Chl)); /*5个I/O口分别输出5v电压*/ P01=SetDACOut(ReadADC(Chl)); P02=SetDACOut(ReadADC(Chl)); P03=SetDACOut(ReadADC(Chl)); P04=SetDACOut(ReadADC(Chl)); } } #include "i2c.h" #include "delay.h" #define _Nop() _nop_() //定义空指令 bit ack; //应答标志位 sbit SDA=P3^6; sbit SCL=P3^7; /*------------------------------------------------ 启动总线 ------------------------------------------------*/ void Start_I2c() { SDA=1; //发送起始条件的数据信号——SCL为高电平期间,SDA由高电平变为低电平 _Nop(); SCL=1; _Nop(); //起始条件建立时间大于4.7us,延时 _Nop(); _Nop(); _Nop(); _Nop(); SDA=0; //发送起始信号 _Nop(); //起始条件锁定时间大于4μ _Nop(); _Nop(); _Nop(); _Nop(); SCL=0; //钳住I2C总线,准备发送或接收数据 _Nop(); _Nop(); } /*------------------------------------------------ 结束总线 ------------------------------------------------*/ void Stop_I2c() { SDA=0; //发送结束条件的数据信号——SCL为高电平期间,SDA由低电平变为高电平 _Nop(); //发送结束条件的时钟信号 SCL=1; //结束条件建立时间大于4μ _Nop(); _Nop(); _Nop(); _Nop(); _Nop(); SDA=1; //发送I2C总线结束信号 _Nop(); _Nop(); _Nop(); _Nop(); } /*---------------------------------------------------------------- 字节数据传送函数 函数原型: void SendByte(unsigned char c); 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 此状态位进行操作.(不应答或非应答都使ack=0 假) 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。 ------------------------------------------------------------------*/ void SendByte(unsigned char c) { unsigned char BitCnt; for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位 { if((c<<BitCnt)&0x80)SDA=1; //判断发送位&是二进制运算符,c左移后和1000000相与, else SDA=0; //例如C=10101010,那么 1 0 1 0 1 0 1 0&1 0 0 0 0 0 0 0=1 0 0 0 0 0 0 0 此时if语句判断为真,则sda =1;发送出去 _Nop();//接着执行循环,C在左移一位后为 0 1 0 1 0 1 0 0和0x80相与结果为 0 0 0 0 0 0 0 0 if语句判断为0,则sda=0 发送出去。 SCL=1; //置时钟线为高,通知被控器开始接收数据位 _Nop(); _Nop(); //保证时钟高电平周期大于4μ _Nop(); _Nop(); _Nop(); SCL=0; } _Nop(); _Nop(); SDA=1; //8位发送完后释放数据线,准备接收应答位 _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); _Nop(); if(SDA==1)ack=0; else ack=1; //判断是否接收到应答信号 SCL=0; _Nop(); _Nop(); } /******************************************* * 设置DAC输出值 * DA转换 * ********************************************/ bit SetDACOut(unsigned char Val) { Start_I2c(); //启动总线 SendByte(0x90); //发送器件地址 if(ack==0) return 1; SendByte(0x40); //写入控制字节 if(ack==0) return 1; SendByte(Val); if(ack==0) return 1; Stop_I2c(); //结束总线 return 0; } /*---------------------------------------------------------------- 字节数据传送函数 函数原型: unsigned char RcvByte(); 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 发完后请用应答函数。 ------------------------------------------------------------------*/ unsigned char RcvByte() { unsigned char retc; unsigned char BitCnt; retc=0; SDA=1; //置数据线为输入方式 for(BitCnt=0;BitCnt<8;BitCnt++) { _Nop(); SCL=0; //置时钟线为低,准备接收数据位 _Nop(); _Nop(); //时钟低电平周期大于4.7us _Nop(); _Nop(); _Nop(); SCL=1; //置时钟线为高使数据线上数据有效 _Nop(); _Nop(); retc=retc<<1; if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中 _Nop(); _Nop(); } SCL=0; _Nop(); _Nop(); return(retc); } /*---------------------------------------------------------------- 应答子函数 原型: void Ack_I2c(void); ----------------------------------------------------------------*/ /*void Ack_I2c(void) { SDA=0; _Nop(); _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); //时钟低电平周期大于4μ _Nop(); _Nop(); _Nop(); SCL=0; //清时钟线,钳住I2C总线以便继续接收 _Nop(); _Nop(); }*/ /*---------------------------------------------------------------- 非应答子函数 原型: void NoAck_I2c(void); ----------------------------------------------------------------*/ void NoAck_I2c(void) { SDA=1; _Nop(); _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); //时钟低电平周期大于4μ _Nop(); _Nop(); _Nop(); SCL=0; //清时钟线,钳住I2C总线以便继续接收 _Nop(); _Nop(); } /*---------------------------------------------------------------- 向无子地址器件发送字节数据函数 函数原型: bit ISendByte(unsigned char sla,ucahr c); 功能: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla. 如果返回1表示操作成功,否则操作有误。 注意: 使用前必须已结束总线。 ----------------------------------------------------------------*/ /*bit ISendByte(unsigned char sla,unsigned char c) { Start_I2c(); //启动总线 SendByte(sla); //发送器件地址 if(ack==0)return(0); SendByte(c); //发送数据 if(ack==0)return(0); Stop_I2c(); //结束总线 return(1); } */ /*---------------------------------------------------------------- 向有子地址器件发送多字节数据函数 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no); 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。 如果返回1表示操作成功,否则操作有误。 注意: 使用前必须已结束总线。 ----------------------------------------------------------------*/ /*bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) { unsigned char i; for(i=0;i<no;i++) { Start_I2c(); //启动总线 SendByte(sla); //发送器件地址 if(ack==0)return(0); SendByte(suba); //发送器件子地址 if(ack==0)return(0); SendByte(*s); //发送数据 if(ack==0)return(0); Stop_I2c(); //结束总线 DelayMs(1); //必须延时等待芯片内部自动处理数据完毕 s++; suba++; } return(1); } */ /*---------------------------------------------------------------- 向无子地址器件读字节数据函数 函数原型: bit IRcvByte(unsigned char sla,ucahr *c); 功能: 从启动总线到发送地址,读数据,结束总线的全过程,从器件地 址sla,返回值在c. 如果返回1表示操作成功,否则操作有误。 注意: 使用前必须已结束总线。 ----------------------------------------------------------------*/ /*bit IRcvByte(unsigned char sla,unsigned char *c) { Start_I2c(); //启动总线 SendByte(sla+1); //发送器件地址 if(ack==0)return(0); *c=RcvByte(); //读取数据 NoAck_I2c(); //发送非就答位 Stop_I2c(); //结束总线 return(1); } */ /*---------------------------------------------------------------- 向有子地址器件读取多字节数据函数 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no); 功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。 如果返回1表示操作成功,否则操作有误。 注意: 使用前必须已结束总线。 ----------------------------------------------------------------*/ /*bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) { unsigned char i; Start_I2c(); //启动总线 SendByte(sla); //发送器件地址 if(ack==0)return(0); SendByte(suba); //发送器件子地址 if(ack==0)return(0); Start_I2c(); SendByte(sla+1); if(ack==0)return(0); for(i=0;i<no-1;i++) { *s=RcvByte(); //发送数据 Ack_I2c(); //发送就答位 s++; } *s=RcvByte(); NoAck_I2c(); //发送非应位 Stop_I2c(); //结束总线 return(1); } */ #include"key.h" #include"delay.h" #include"i2c.h" #include"display.h" sbit S17=P3^3; //独立按键 sbit S18=P3^2; sbit S19=P3^1; sbit S20=P3^0; unsigned char TempData[8]; /*------------------------------------------------ 按键扫描函数,返回扫描键值 程控放大倍数 ------------------------------------------------*/ unsigned char KeyScan() { static unsigned char volt = 0; if(!S20) //如果检测到低电平,说明按键按下 { /*sbit S20=P3^0; 依次-6*/ DelayMs(10); //延时去抖,一般10-20ms if(!S20) //再次确认按键是否按下,没有按下则退出 { while(!S20);//如果确认按下按键等待按键释放,没有释放则一直等待 { if(volt<255) /*不同按键输出的不同电压不懂*/ { volt=volt+500; SetDACOut(volt*0.51);//转换为AD输出值 TempData[8]=volt*0.51; ShowData((unsigned char)(volt*0.51),TempData); Display(0,4); } } return (1); } } if(!S19) //如果检测到低电平,说明按键按下 { /*依次+6*/ DelayMs(10); //延时去抖,一般10-20ms if(!S19) //再次确认按键是否按下,没有按下则退出 { while(!S19);//如果确认按下按键等待按键释放,没有释放则一直等待 { if(volt>0) { volt=volt-500; SetDACOut(volt*0.51); TempData[8]=volt*0.51; ShowData((unsigned char)(volt*0.51),TempData); Display(0,4); } } return (2); } } if(!S18) //如果检测到低电平,说明按键按下 { /*乱跳????*/ DelayMs(10); //延时去抖,一般10-20ms if(!S18) //再次确认按键是否按下,没有按下则退出 { while(!S18);//如果确认按下按键等待按键释放,没有释放则一直等待 { if(volt<255) { volt=volt+100; SetDACOut(volt*0.51); TempData[8]=volt*0.51; ShowData((unsigned char)(volt*0.51),TempData); Display(0,4); } } return (3); } } if(!S17) //如果检测到低电平,说明按键按下 { /*乱跳????*/ DelayMs(10); //延时去抖,一般10-20ms if(!S17) //再次确认按键是否按下,没有按下则退出 { while(!S17);//如果确认按下按键等待按键释放,没有释放则一直等待 { if(volt>0) { volt=volt-100; SetDACOut(volt*0.51); TempData[8]=volt*0.51; ShowData((unsigned char)(volt*0.51),TempData); Display(0,4); } } return (4); } } return 0; } 下载程序到单片机后,数码管显示值自动跳转 且无规律 不知道哪里出错了?菜鸟求大神解答 万分感谢!

Python数据挖掘简易入门

&nbsp; &nbsp; &nbsp; &nbsp; 本课程为Python数据挖掘方向的入门课程,课程主要以真实数据为基础,详细介绍数据挖掘入门的流程和使用Python实现pandas与numpy在数据挖掘方向的运用,并深入学习如何运用scikit-learn调用常用的数据挖掘算法解决数据挖掘问题,为进一步深入学习数据挖掘打下扎实的基础。

HoloLens2开发入门教程

本课程为HoloLens2开发入门教程,讲解部署开发环境,安装VS2019,Unity版本,Windows SDK,创建Unity项目,讲解如何使用MRTK,编辑器模拟手势交互,打包VS工程并编译部署应用到HoloLens上等。

2019 Python开发者日-培训

本次活动将秉承“只讲技术,拒绝空谈”的理念,邀请十余位身处一线的Python技术专家,重点围绕Web开发、自动化运维、数据分析、人工智能等技术模块,分享真实生产环境中使用Python应对IT挑战的真知灼见。此外,针对不同层次的开发者,大会还安排了深度培训实操环节,为开发者们带来更多深度实战的机会。

Only老K说-爬取妹子图片(简单入门)

安装第三方请求库 requests 被网站禁止了访问 原因是我们是Python过来的 重新给一段 可能还是存在用不了,使用网页的 编写代码 上面注意看匹配内容 User-Agent:请求对象 AppleWebKit:请求内核 Chrome浏览器 //请求网页 import requests import re //正则表达式 就是去不规则的网页里面提取有规律的信息 headers = { 'User-Agent':'存放浏览器里面的' } response = requests.get

2020_五一数学建模_C题_整理后的数据.zip

该数据是我的程序读取的数据,仅供参考,问题的解决方案:https://blog.csdn.net/qq_41228463/article/details/105993051

R语言入门基础

本课程旨在帮助学习者快速入门R语言: 课程系统详细地介绍了使用R语言进行数据处理的基本思路和方法。 课程能够帮助初学者快速入门数据处理。 课程通过大量的案例详细地介绍了如何使用R语言进行数据分析和处理 课程操作实际案例教学,通过编写代码演示R语言的基本使用方法和技巧

人才招聘系统PHP+MySQL源码

PHP 5.0及以上 + MySQL 5.0及以上 开发的人才招聘系统完全可运行源码,按照操作说明简单配置即可运行。学习PHPWEB应用的完整系统程序源码。

Java基础知识面试题(2020最新版)

文章目录Java概述何为编程什么是Javajdk1.5之后的三大版本JVM、JRE和JDK的关系什么是跨平台性?原理是什么Java语言有哪些特点什么是字节码?采用字节码的最大好处是什么什么是Java程序的主类?应用程序和小程序的主类有何不同?Java应用程序与小程序之间有那些差别?Java和C++的区别Oracle JDK 和 OpenJDK 的对比基础语法数据类型Java有哪些数据类型switc...

python可视化分析(matplotlib、seaborn、ggplot2)

python可视化分析总结(matplotlib、seaborn、ggplot)一、matplotlib库1、基本绘图命令3、图形参数设置4、特殊统计图的绘制4.1 数学函数图4.2 气泡图4.1 三维曲面图二、seaborn库1、常用统计图1.1 箱线图1.2 小提琴图1.3 点图1.4 条图与计数图1.5 分组图1.6 概率分布图2、联合图3、配对图三、ggplot库1、图层画法+常用图形2、快速绘图 一、matplotlib库 1、基本绘图命令 import matplotlib.pyplot as

Vue.js 2.0之全家桶系列视频课程

基于新的Vue.js 2.3版本, 目前新全的Vue.js教学视频,让你少走弯路,直达技术前沿! 1. 包含Vue.js全家桶(vue.js、vue-router、axios、vuex、vue-cli、webpack、ElementUI等) 2. 采用笔记+代码案例的形式讲解,通俗易懂

初级玩转Linux+Ubuntu(嵌入式开发基础课程)

课程主要面向嵌入式Linux初学者、工程师、学生 主要从一下几方面进行讲解: 1.linux学习路线、基本命令、高级命令 2.shell、vi及vim入门讲解 3.软件安装下载、NFS、Samba、FTP等服务器配置及使用

人工智能-计算机视觉实战之路(必备算法+深度学习+项目实战)

系列课程主要分为3大阶段:(1)首先掌握计算机视觉必备算法原理,结合Opencv进行学习与练手,通过实际视项目进行案例应用展示。(2)进军当下最火的深度学习进行视觉任务实战,掌握深度学习中必备算法原理与网络模型架构。(3)结合经典深度学习框架与实战项目进行实战,基于真实数据集展开业务分析与建模实战。整体风格通俗易懂,项目驱动学习与就业面试。 建议同学们按照下列顺序来进行学习:1.Python入门视频课程 2.Opencv计算机视觉实战(Python版) 3.深度学习框架-PyTorch实战/人工智能框架实战精讲:Keras项目 4.Python-深度学习-物体检测实战 5.后续实战课程按照自己喜好选择就可以

【大总结2】大学两年,写了这篇几十万字的干货总结

本文十天后设置为粉丝可见,喜欢的提前关注 不要白嫖请点赞 不要白嫖请点赞 不要白嫖请点赞 文中提到的书我都有电子版,可以评论邮箱发给你。 文中提到的书我都有电子版,可以评论邮箱发给你。 文中提到的书我都有电子版,可以评论邮箱发给你。 本篇文章应该算是Java后端开发技术栈的,但是大部分是基础知识,所以我觉得对任何方向都是有用的。 1、数据结构 数据结构是计算机存储、...

lena全身原图(非256*256版本,而是全身原图)

lena全身原图(非256*256版本,而是全身原图) lena原图很有意思,我们通常所用的256*256图片是在lena原图上截取了头部部分的256*256正方形得到的. 原图是花花公子杂志上的一个

【项目实战】 图书信息管理系统(Maven,mybatis)(第一个自己独立完成的项目)

《程序设计综合训练实践报告》 此项目为图书信息管理系统,是一个采用了mysql+mybatis框架+java编写的maven项目

图书管理系统(Java + Mysql)我的第一个完全自己做的实训项目

图书管理系统 Java + MySQL 完整实训代码,MVC三层架构组织,包含所有用到的图片资源以及数据库文件,大三上学期实训,注释很详细,按照阿里巴巴Java编程规范编写

Python入门视频精讲

Python入门视频培训课程以通俗易懂的方式讲解Python核心技术,Python基础,Python入门。适合初学者的教程,让你少走弯路! 课程内容包括:1.Python简介和安装 、2.第一个Python程序、PyCharm的使用 、3.Python基础、4.函数、5.高级特性、6.面向对象、7.模块、8.异常处理和IO操作、9.访问数据库MySQL。教学全程采用笔记+代码案例的形式讲解,通俗易懂!!!

20行代码教你用python给证件照换底色

20行代码教你用python给证件照换底色

2018年全国大学生计算机技能应用大赛决赛 大题

2018年全国大学生计算机技能应用大赛决赛大题,程序填空和程序设计(侵删)

MySQL数据库从入门到实战应用

限时福利1:购课进答疑群专享柳峰(刘运强)老师答疑服务 限时福利2:购课后添加学习助手(微信号:csdn590),按消息提示即可领取编程大礼包! 为什么说每一个程序员都应该学习MySQL? 根据《2019-2020年中国开发者调查报告》显示,超83%的开发者都在使用MySQL数据库。 使用量大同时,掌握MySQL早已是运维、DBA的必备技能,甚至部分IT开发岗位也要求对数据库使用和原理有深入的了解和掌握。 学习编程,你可能会犹豫选择 C++ 还是 Java;入门数据科学,你可能会纠结于选择 Python 还是 R;但无论如何, MySQL 都是 IT 从业人员不可或缺的技能! 【课程设计】 在本课程中,刘运强老师会结合自己十多年来对MySQL的心得体会,通过课程给你分享一条高效的MySQL入门捷径,让学员少走弯路,彻底搞懂MySQL。 本课程包含3大模块:&nbsp; 一、基础篇: 主要以最新的MySQL8.0安装为例帮助学员解决安装与配置MySQL的问题,并对MySQL8.0的新特性做一定介绍,为后续的课程展开做好环境部署。 二、SQL语言篇: 本篇主要讲解SQL语言的四大部分数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL,学会熟练对库表进行增删改查等必备技能。 三、MySQL进阶篇: 本篇可以帮助学员更加高效的管理线上的MySQL数据库;具备MySQL的日常运维能力,语句调优、备份恢复等思路。 &nbsp;

C/C++学习指南全套教程

C/C++学习的全套教程,从基本语法,基本原理,到界面开发、网络开发、Linux开发、安全算法,应用尽用。由毕业于清华大学的业内人士执课,为C/C++编程爱好者的教程。

C/C++跨平台研发从基础到高阶实战系列套餐

一 专题从基础的C语言核心到c++ 和stl完成基础强化; 二 再到数据结构,设计模式完成专业计算机技能强化; 三 通过跨平台网络编程,linux编程,qt界面编程,mfc编程,windows编程,c++与lua联合编程来完成应用强化 四 最后通过基于ffmpeg的音视频播放器,直播推流,屏幕录像,

我以为我对Mysql事务很熟,直到我遇到了阿里面试官

太惨了,面试又被吊打

专为程序员设计的数学课

<p> 限时福利限时福利,<span>15000+程序员的选择!</span> </p> <p> 购课后添加学习助手(微信号:csdn590),按提示消息领取编程大礼包!并获取讲师答疑服务! </p> <p> <br> </p> <p> 套餐中一共包含5门程序员必学的数学课程(共47讲) </p> <p> 课程1:《零基础入门微积分》 </p> <p> 课程2:《数理统计与概率论》 </p> <p> 课程3:《代码学习线性代数》 </p> <p> 课程4:《数据处理的最优化》 </p> <p> 课程5:《马尔可夫随机过程》 </p> <p> <br> </p> <p> 哪些人适合学习这门课程? </p> <p> 1)大学生,平时只学习了数学理论,并未接触如何应用数学解决编程问题; </p> <p> 2)对算法、数据结构掌握程度薄弱的人,数学可以让你更好的理解算法、数据结构原理及应用; </p> <p> 3)看不懂大牛代码设计思想的人,因为所有的程序设计底层逻辑都是数学; </p> <p> 4)想学习新技术,如:人工智能、机器学习、深度学习等,这门课程是你的必修课程; </p> <p> 5)想修炼更好的编程内功,在遇到问题时可以灵活的应用数学思维解决问题。 </p> <p> <br> </p> <p> 在这门「专为程序员设计的数学课」系列课中,我们保证你能收获到这些:<br> <br> <span> </span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">①价值300元编程课程大礼包</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">②应用数学优化代码的实操方法</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">③数学理论在编程实战中的应用</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">④程序员必学的5大数学知识</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">⑤人工智能领域必修数学课</span> </p> <p> <br> 备注:此课程只讲程序员所需要的数学,即使你数学基础薄弱,也能听懂,只需要初中的数学知识就足矣。<br> <br> 如何听课? </p> <p> 1、登录CSDN学院 APP 在我的课程中进行学习; </p> <p> 2、登录CSDN学院官网。 </p> <p> <br> </p> <p> 购课后如何领取免费赠送的编程大礼包和加入答疑群? </p> <p> 购课后,添加助教微信:<span> csdn590</span>,按提示领取编程大礼包,或观看付费视频的第一节内容扫码进群答疑交流! </p> <p> <img src="https://img-bss.csdn.net/201912251155398753.jpg" alt=""> </p>

Eclipse archetype-catalog.xml

Eclipse Maven 创建Web 项目报错 Could not resolve archetype org.apache.maven.archetypes:maven-archetype-web

使用TensorFlow+keras快速构建图像分类模型

课程分为两条主线: 1&nbsp;从Tensorflow的基础知识开始,全面介绍Tensorflow和Keras相关内容。通过大量实战,掌握Tensorflow和Keras经常用到的各种建模方式,参数优化方法,自定义参数和模型的手段,以及对训练结果评估与分析的技巧。 2&nbsp;从机器学习基础算法开始,然后进入到图像分类领域,使用MNIST手写数据集和CIFAR10图像数据集,从简单神经网络到深度神经网络,再到卷积神经网络,最终完成复杂模型:残差网络的搭建。完成这条主线,学员将可以自如地使用机器学习的手段来达到图像分类的目的。

Python代码实现飞机大战

文章目录经典飞机大战一.游戏设定二.我方飞机三.敌方飞机四.发射子弹五.发放补给包六.主模块 经典飞机大战 源代码以及素材资料(图片,音频)可从下面的github中下载: 飞机大战源代码以及素材资料github项目地址链接 ————————————————————————————————————————————————————————— 不知道大家有没有打过飞机,喜不喜欢打飞机。当我第一次接触这个东西的时候,我的内心是被震撼到的。第一次接触打飞机的时候作者本人是身心愉悦的,因为周边的朋友都在打飞机, 每

最近面试Java后端开发的感受:如果就以平时项目经验来面试,通过估计很难,不信你来看看

在上周,我密集面试了若干位Java后端的候选人,工作经验在3到5年间。我的标准其实不复杂:第一能干活,第二Java基础要好,第三最好熟悉些分布式框架,我相信其它公司招初级开发时,应该也照着这个标准来面的。 我也知道,不少候选人能力其实不差,但面试时没准备或不会说,这样的人可能在进团队干活后确实能达到期望,但可能就无法通过面试,但面试官总是只根据面试情况来判断。 但现实情况是,大多数人可能面试前没准备,或准备方法不得当。要知道,我们平时干活更偏重于业务,不可能大量接触到算法,数据结构,底层代码这类面试必问

三个项目玩转深度学习(附1G源码)

从事大数据与人工智能开发与实践约十年,钱老师亲自见证了大数据行业的发展与人工智能的从冷到热。事实证明,计算机技术的发展,算力突破,海量数据,机器人技术等,开启了第四次工业革命的序章。深度学习图像分类一直是人工智能的经典任务,是智慧零售、安防、无人驾驶等机器视觉应用领域的核心技术之一,掌握图像分类技术是机器视觉学习的重中之重。针对现有线上学习的特点与实际需求,我们开发了人工智能案例实战系列课程。打造:以项目案例实践为驱动的课程学习方式,覆盖了智能零售,智慧交通等常见领域,通过基础学习、项目案例实践、社群答疑,三维立体的方式,打造最好的学习效果。

微信小程序开发实战之番茄时钟开发

微信小程序番茄时钟视频教程,本课程将带着各位学员开发一个小程序初级实战类项目,针对只看过官方文档而又无从下手的开发者来说,可以作为一个较好的练手项目,对于有小程序开发经验的开发者而言,可以更好加深对小程序各类组件和API 的理解,为更深层次高难度的项目做铺垫。

相关热词 c#分级显示数据 c# 不区分大小写替换 c#中调用就java c#正则表达式 验证小数 c# vscode 配置 c#三维数组能存多少数据 c# 新建excel c#多个文本框 c#怎么创建tcp通讯 c# mvc 电子病例
立即提问