以下代码来自学习江科大自化协和手把手教你学51单片机后的整合

- //LCD1602.h
- #ifndef __LCD1602_H__
- #define __LCD1602_H__
-
- //用户调用函数:
- void LCD_Init();
- void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
- void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
- void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
- void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
- void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
- void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
-
- #endif
-
-
- //LCD1602.c
-
- #include
-
- //引脚配置:
- sbit LCD_RS=P2^6;
- sbit LCD_RW=P2^5;
- sbit LCD_EN=P2^7;
- #define LCD_DataPort P0
-
- //函数定义:
- /**
- * @brief LCD1602延时函数,12MHz调用可延时1ms
- * @param 无
- * @retval 无
- */
- void LCD_Delay()
- {
- unsigned char i, j;
-
- i = 2;
- j = 239;
- do
- {
- while (--j);
- } while (--i);
- }
-
- /**
- * @brief LCD1602写命令
- * @param Command 要写入的命令
- * @retval 无
- */
- void LCD_WriteCommand(unsigned char Command)
- {
- LCD_RS=0;
- LCD_RW=0;
- LCD_DataPort=Command;
- LCD_EN=1;
- LCD_Delay();
- LCD_EN=0;
- LCD_Delay();
- }
-
- /**
- * @brief LCD1602写数据
- * @param Data 要写入的数据
- * @retval 无
- */
- void LCD_WriteData(unsigned char Data)
- {
- LCD_RS=1;
- LCD_RW=0;
- LCD_DataPort=Data;
- LCD_EN=1;
- LCD_Delay();
- LCD_EN=0;
- LCD_Delay();
- }
-
- /**
- * @brief LCD1602设置光标位置
- * @param Line 行位置,范围:1~2
- * @param Column 列位置,范围:1~16
- * @retval 无
- */
- void LCD_SetCursor(unsigned char Line,unsigned char Column)
- {
- if(Line==1)
- {
- LCD_WriteCommand(0x80|(Column-1));
- }
- else if(Line==2)
- {
- LCD_WriteCommand(0x80|(Column-1+0x40));
- }
- }
-
- /**
- * @brief LCD1602初始化函数
- * @param 无
- * @retval 无
- */
- void LCD_Init()
- {
- LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
- LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
- LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
- LCD_WriteCommand(0x01);//光标复位,清屏
- }
-
- /**
- * @brief 在LCD1602指定位置上显示一个字符
- * @param Line 行位置,范围:1~2
- * @param Column 列位置,范围:1~16
- * @param Char 要显示的字符
- * @retval 无
- */
- void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
- {
- LCD_SetCursor(Line,Column);
- LCD_WriteData(Char);
- }
-
- /**
- * @brief 在LCD1602指定位置开始显示所给字符串
- * @param Line 起始行位置,范围:1~2
- * @param Column 起始列位置,范围:1~16
- * @param String 要显示的字符串
- * @retval 无
- */
- void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=0;String[i]!='\0';i++)
- {
- LCD_WriteData(String[i]);
- }
- }
-
- /**
- * @brief 返回值=X的Y次方
- */
- int LCD_Pow(int X,int Y)
- {
- unsigned char i;
- int Result=1;
- for(i=0;i
- {
- Result*=X;
- }
- return Result;
- }
-
- /**
- * @brief 在LCD1602指定位置开始显示所给数字
- * @param Line 起始行位置,范围:1~2
- * @param Column 起始列位置,范围:1~16
- * @param Number 要显示的数字,范围:0~65535
- * @param Length 要显示数字的长度,范围:1~5
- * @retval 无
- */
- void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
- }
- }
-
- /**
- * @brief 在LCD1602指定位置开始以有符号十进制显示所给数字
- * @param Line 起始行位置,范围:1~2
- * @param Column 起始列位置,范围:1~16
- * @param Number 要显示的数字,范围:-32768~32767
- * @param Length 要显示数字的长度,范围:1~5
- * @retval 无
- */
- void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
- {
- unsigned char i;
- unsigned int Number1;
- LCD_SetCursor(Line,Column);
- if(Number>=0)
- {
- LCD_WriteData('+');
- Number1=Number;
- }
- else
- {
- LCD_WriteData('-');
- Number1=-Number;
- }
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
- }
- }
-
- /**
- * @brief 在LCD1602指定位置开始以十六进制显示所给数字
- * @param Line 起始行位置,范围:1~2
- * @param Column 起始列位置,范围:1~16
- * @param Number 要显示的数字,范围:0~0xFFFF
- * @param Length 要显示数字的长度,范围:1~4
- * @retval 无
- */
- void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i,SingleNumber;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- SingleNumber=Number/LCD_Pow(16,i-1)%16;
- if(SingleNumber<10)
- {
- LCD_WriteData(SingleNumber+'0');
- }
- else
- {
- LCD_WriteData(SingleNumber-10+'A');
- }
- }
- }
-
- /**
- * @brief 在LCD1602指定位置开始以二进制显示所给数字
- * @param Line 起始行位置,范围:1~2
- * @param Column 起始列位置,范围:1~16
- * @param Number 要显示的数字,范围:0~1111 1111 1111 1111
- * @param Length 要显示数字的长度,范围:1~16
- * @retval 无
- */
- void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
- }
- }
-
- //***********************************************************************************//********************
- //DS1302.h
- #ifndef __DS1302_H__
- #define __DS1302_H__
-
- char DS1302_data[];
- extern unsigned char TimeSetFlashFlag;
-
- void Time_Show();
- void LCD_Show();
- void LCD_Show_Button();
-
- void DS1302_Init();
- void DS1302_WriteByte(unsigned char command,unsigned char Data);
- unsigned char DS1302_ReadByte(unsigned char command);
- void DS1302_SetTime();
- void DS1302_ReadTime();
-
- #endif
-
-
- //DS1302.c
- #include
- #include "LCD1602.h"
- #include "Key.h"
-
- sbit DS1302_SCLK = P3^6;
- sbit DS1302_IO = P3^4;
- sbit DS1302_CE = P3^5;
-
- char DS1302_data[] = {21,12,31,23,59,56,2}; //定义年,月,日,时,分,秒,星期
-
- unsigned char TimeSetFlashFlag; //时间设置闪烁标志位。
-
- #define DS1302_sec 0x80 //写地址最后一位为零,如果是读就让它|0x01,在DS1302_ReadByte()中已经置1了,所以不用再定义0x81
- #define DS1302_min 0x82
- #define DS1302_hour 0x84
- #define DS1302_date 0x86 //日期
- #define DS1302_mon 0x88
- #define DS1302_day 0x8A //星期
- #define DS1302_year 0x8C
- #define DS1302_wp 0x8E //写保护
-
- /************BCD码转换******************/
- //DEC=BCD/16*10+BCD%16
- //BCD=DEC/10*16+DEC%10
-
- void DS1302_Init()
- {
- DS1302_CE = 0;
- DS1302_SCLK = 0;
- }
-
- void DS1302_WriteByte(unsigned char command,unsigned char Data)
- {
- // DS1302_CE = 1;
- //
- // DS1302_IO = command&0x01;
- // DS1302_SCLK = 1; //一个上升延写入,
- // DS1302_SCLK = 0; //随后又下降,为下一个上升延准备.
- //
- // DS1302_IO = command&0x02;
- // DS1302_SCLK = 1; //一个上升延写入,
- // DS1302_SCLK = 0; //随后又下降,为下一个上升延准备.
- // . 查DS1302数据手册得知上升下降最小为50ns,结合单片机
- // . 执行一条语句的时间为微秒级,所以中间不用延迟.
- // .优化如下:
- unsigned char i;
- DS1302_CE = 1;
- for(i=0;i<8;i++)
- {
- DS1302_IO = command&(0x01<
- DS1302_SCLK = 1; //一个上升延写入,
- DS1302_SCLK = 0; //随后又下降,为下一个上升延准备.
- }
-
- //以上是时序图的前半段,以下是后半段
- for(i=0;i<8;i++)
- {
- DS1302_IO = Data&(0x01<
- DS1302_SCLK = 1; //一个上升延写入,
- DS1302_SCLK = 0; //随后又下降,为下一个上升延准备.
- }
- DS1302_CE = 0;
-
- }
-
- unsigned char DS1302_ReadByte(unsigned char command)
- {
-
- unsigned char i;
- unsigned char Data = 0x00;
- command |= 0x01; //读的最低位肯定为1
- DS1302_CE = 1;
- for(i=0;i<8;i++)
- {
- DS1302_IO = command&(0x01<
- DS1302_SCLK = 0; //先一个下降延,与初始一样,目的是最后一次循环后能落到读数据之前.
- DS1302_SCLK = 1; //来一个上升延写入命令.
- }
- //以上是时序图的前半段,以下是后半段
- for(i=0;i<8;i++)
- {
- DS1302_SCLK = 1; //接着上面重复置1就可以和时序一样.加起来等于15个上升延.
- DS1302_SCLK = 0; //下降延读出数据.
- if(DS1302_IO)
- {
- Data |= (0x01<
- }
- }
- DS1302_CE = 0;
- DS1302_IO = 0;
- return Data;
- }
-
- void DS1302_SetTime()
- {
- DS1302_WriteByte(DS1302_wp,0x00); //关闭写保护
- DS1302_WriteByte(DS1302_year,DS1302_data[0]/10*16+DS1302_data[0]%10);
- DS1302_WriteByte(DS1302_mon,DS1302_data[1]/10*16+DS1302_data[1]%10);
- DS1302_WriteByte(DS1302_date,DS1302_data[2]/10*16+DS1302_data[2]%10);
- DS1302_WriteByte(DS1302_hour,DS1302_data[3]/10*16+DS1302_data[3]%10);
- DS1302_WriteByte(DS1302_min,DS1302_data[4]/10*16+DS1302_data[4]%10);
- DS1302_WriteByte(DS1302_sec,DS1302_data[5]/10*16+DS1302_data[5]%10);
- DS1302_WriteByte(DS1302_day,DS1302_data[6]/10*16+DS1302_data[6]%10);
- DS1302_WriteByte(DS1302_wp,0x80); //打开写保护
- }
-
- void DS1302_ReadTime()
- {
- unsigned char tmp;
- tmp = DS1302_ReadByte(DS1302_year);
- DS1302_data[0] = tmp/16*10+tmp%16;
- tmp = DS1302_ReadByte(DS1302_mon);
- DS1302_data[1] = tmp/16*10+tmp%16;
- tmp = DS1302_ReadByte(DS1302_date);
- DS1302_data[2] = tmp/16*10+tmp%16;
- tmp = DS1302_ReadByte(DS1302_hour);
- DS1302_data[3] = tmp/16*10+tmp%16;
- tmp = DS1302_ReadByte(DS1302_min);
- DS1302_data[4] = tmp/16*10+tmp%16;
- tmp = DS1302_ReadByte(DS1302_sec);
- DS1302_data[5] = tmp/16*10+tmp%16;
- tmp = DS1302_ReadByte(DS1302_day);
- DS1302_data[6] = tmp/16*10+tmp%16;
- }
-
- void LCD_Show_Button() //设置时数字闪烁
- {
- if(index==0 && TimeSetFlashFlag==1)
- {
- LCD_ShowString(1,1," ");
- }
- else
- {
- LCD_ShowNum(1,1,DS1302_data[0],2);
- }
- if(index==1 && TimeSetFlashFlag==1)
- {
- LCD_ShowString(1,4," ");
- }
- else
- {
- LCD_ShowNum(1,4,DS1302_data[1],2);
- }
- if(index==2 && TimeSetFlashFlag==1)
- {
- LCD_ShowString(1,7," ");
- }
- else
- {
- LCD_ShowNum(1,7,DS1302_data[2],2);
- }
- if(index==3 && TimeSetFlashFlag==1)
- {
- LCD_ShowString(2,1," ");
- }
- else
- {
- LCD_ShowNum(2,1,DS1302_data[3],2);
- }
- if(index==4 && TimeSetFlashFlag==1)
- {
- LCD_ShowString(2,4," ");
- }
- else
- {
- LCD_ShowNum(2,4,DS1302_data[4],2);
- }
- if(index==5 && TimeSetFlashFlag==1)
- {
- LCD_ShowString(2,7," ");
- }
- else
- {
- LCD_ShowNum(2,7,DS1302_data[5],2);
- }
-
- }
-
- void LCD_Show()
- {
- LCD_ShowNum(1,1,DS1302_data[0],2);
- LCD_ShowNum(1,4,DS1302_data[1],2);
- LCD_ShowNum(1,7,DS1302_data[2],2);
- LCD_ShowNum(2,1,DS1302_data[3],2);
- LCD_ShowNum(2,4,DS1302_data[4],2);
- LCD_ShowNum(2,7,DS1302_data[5],2);
- }
-
- void Time_Show()
- {
- DS1302_ReadTime(); //读取时间.
- LCD_Show();
- }
-
- //***********************************************************************************//********************************
- //key.h
- #ifndef __KEY_H_
- #define __KEY_H_
-
- extern unsigned char MODE;
- extern unsigned char KeySta[4][4];
- extern unsigned long pdata KeyDownTime[4][4];
- extern unsigned char index;
- void KeyAction(unsigned char keycode);
- void KeyDriver();
- void KeyScan();
- #endif
-
- key.c
- #include "LCD1602.H"
- #include
- #include "DS1302.H"
-
- unsigned char MODE = 0;
- unsigned char index = 0;
- unsigned char KeySta[4][4] = {{1,1,1,1},
- {1,1,1,1},
- {1,1,1,1},
- {1,1,1,1}
- };
-
- unsigned char code KeyCodeMap[4][4]={
- {0x31,0x32,0x33,0x26}, //数字键1,数字键2,数字键3,向上键
- {0x34,0x35,0x36,0x25}, //数字键4,数字键5,数字键6,向左键
- {0x37,0x38,0x39,0x28}, //数字键7,数字键8,数字键9,向下键
- {0x30,0x1B,0x0D,0x27} //数字键0,Esc键,回车键,向右键
- };
- unsigned long pdata KeyDownTime[4][4] = {
- {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}
- };
- void KeyAction(unsigned char keycode)
- {
-
- if((keycode>=0x30)&&(keycode<=0x39)) //如果是数字0~9
- {
-
- }
- else if(keycode==0x25) //向左 ,设为切换模式
- {
- MODE = !MODE;
- }
- else if(keycode==0x26) //如果是向上键 ,加
- {
- DS1302_data[index]++;
- if(DS1302_data[0]>99){DS1302_data[0]=0;}//年越界判断
- if(DS1302_data[1]>12){DS1302_data[1]=1;}//月越界判断
- if( DS1302_data[1]==1 || DS1302_data[1]==3 || DS1302_data[1]==5 || DS1302_data[1]==7 ||
- DS1302_data[1]==8 || DS1302_data[1]==10 || DS1302_data[1]==12)//日越界判断
- {
- if(DS1302_data[2]>31){DS1302_data[2]=1;}//大月
- }
- else if(DS1302_data[1]==4 || DS1302_data[1]==6 || DS1302_data[1]==9 || DS1302_data[1]==11)
- {
- if(DS1302_data[2]>30){DS1302_data[2]=1;}//小月
- }
- else if(DS1302_data[1]==2)
- {
- if(DS1302_data[0]%4==0)
- {
- if(DS1302_data[2]>29){DS1302_data[2]=1;}//闰年2月
- }
- else
- {
- if(DS1302_data[2]>28){DS1302_data[2]=1;}//平年2月
- }
- }
- if(DS1302_data[3]>23){DS1302_data[3]=0;}//时越界判断
- if(DS1302_data[4]>59){DS1302_data[4]=0;}//分越界判断
- if(DS1302_data[5]>59){DS1302_data[5]=0;}//秒越界判断
- }
- else if(keycode==0x27) //如果是向右键 ,切换时间数组索引
- {
- index++;
- index %= 6;
- }
- else if(keycode==0x28)//如果是向下键,减
- {
- DS1302_data[index]--;
- if(DS1302_data[0]<0){DS1302_data[0]=99;}//年越界判断
- if(DS1302_data[1]<1){DS1302_data[1]=12;}//月越界判断
- if( DS1302_data[1]==1 || DS1302_data[1]==3 || DS1302_data[1]==5 || DS1302_data[1]==7 ||
- DS1302_data[1]==8 || DS1302_data[1]==10 || DS1302_data[1]==12)//日越界判断
- {
- if(DS1302_data[2]<1){DS1302_data[2]=31;}//大月
- if(DS1302_data[2]>31){DS1302_data[2]=1;}
- }
- else if(DS1302_data[1]==4 || DS1302_data[1]==6 || DS1302_data[1]==9 || DS1302_data[1]==11)
- {
- if(DS1302_data[2]<1){DS1302_data[2]=30;}//小月
- if(DS1302_data[2]>30){DS1302_data[2]=1;}
- }
- else if(DS1302_data[1]==2)
- {
- if(DS1302_data[0]%4==0)
- {
- if(DS1302_data[2]<1){DS1302_data[2]=29;}//闰年2月
- if(DS1302_data[2]>29){DS1302_data[2]=1;}
- }
- else
- {
- if(DS1302_data[2]<1){DS1302_data[2]=28;}//平年2月
- if(DS1302_data[2]>28){DS1302_data[2]=1;}
- }
- }
- if(DS1302_data[3]<0){DS1302_data[3]=23;}//时越界判断
- if(DS1302_data[4]<0){DS1302_data[4]=59;}//分越界判断
- if(DS1302_data[5]<0){DS1302_data[5]=59;}//秒越界判断
- }
- else if(keycode==0x1B) //如果是回车键
- {
-
- }
- }
-
- void KeyDriver()
- {
- static unsigned char backup[4][4] = { {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};
- unsigned char i,j;
- static unsigned long pdata TimeAdd[4][4] = {
- {1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000},{1000,1000,1000,1000}
- };
- for(i=0;i<4;i++)
- {
- for(j=0;j<4;j++)
- {
- if(backup[i][j] != KeySta[i][j])
- {
- if(backup[i][j] == 0)
- {
- KeyAction(KeyCodeMap[i][j]);
- }
- backup[i][j] = KeySta[i][j];
- }
- if(KeyDownTime[i][j] > 0)
- { //LCD_ShowNum(1,5,KeyDownTime[i][j],5);
- if(KeyDownTime[i][j] >= TimeAdd[i][j])
- { //LCD_ShowNum(2,8,KeyDownTime[i][j],5);
- KeyAction(KeyCodeMap[i][j]);
- TimeAdd[i][j] += 80; //设置长按时跳动的速度,越小越快
- }
- }
- else
- TimeAdd[i][j] = 1000;
-
- }
- }
- }
-
- void KeyScan()
- {
- static unsigned char keyout = 0;
- unsigned char i = 0;
- static unsigned char keybuf[4][4] = {{0xFF,0xFF,0xFF,0xFF},
- {0xFF,0xFF,0xFF,0xFF},
- {0xFF,0xFF,0xFF,0xFF},
- {0xFF,0xFF,0xFF,0xFF}
- };
- keybuf[keyout][0] = (keybuf[keyout][0]<<1) | P14; //所以每行要左移8次,4行就左移32次,32毫秒就能跳出抖动
- keybuf[keyout][1] = (keybuf[keyout][1]<<1) | P15;
- keybuf[keyout][2] = (keybuf[keyout][2]<<1) | P16;
- keybuf[keyout][3] = (keybuf[keyout][3]<<1) | P17;
-
- for(i=0;i<4;i++)
- {
- if((keybuf[keyout][i] & 0xFF) == 0x00) //0x00表示后8位为0就判断为0,因为初始值
- { //为0xFF,所以至少要进入8次中断,左移8次
- KeySta[keyout][i] = 0; //与0xFF才可能等于0x00
- KeyDownTime[keyout][i] += 4; //所以这这里要加上4毫秒。
- }
- else if((keybuf[keyout][i] & 0xFF) == 0xFF) //0xFF表示8位为1就判断为1
- {
- KeySta[keyout][i] = 1;
- KeyDownTime[keyout][i] = 0;
- }
- }
- keyout++;
- // if(keyout>=3)
- // {
- // keyout = 0;
- // }
- keyout &= 0x03;
- switch(keyout)
- {
- //case 0: P00=1;P01=1;P02=1;P03=0;break;
- //case 1: P00=1;P01=1;P02=0;P03=1;break;
- //case 2: P00=1;P01=0;P02=1;P03=1;break;
- //case 3: P00=0;P01=1;P02=1;P03=1;break;
- //优化后如下:
- case 0: P10=1;P13=0; break;
- case 1: P13=1;P12=0; break;
- case 2: P12=1;P11=0; break;
- case 3: P11=1;P10=0; break;
- default: break;
- }
- }
-
- //***********************************************************************************//***********
-
- mani.c
- #include
- #include "LCD1602.h"
- #include "DS1302.h"
- #include "Key.h"
-
- void main()
- {
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0x18; //设置定时初值,1毫秒@12.000MHz
- TH0 = 0xFC; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- EA = 1;
- ET0 = 1;
-
- LCD_Init();
- DS1302_Init();
- LCD_ShowString(1,1," - -");
- LCD_ShowString(2,1," : :");
- DS1302_SetTime(); //设置时间,用数组里面的数值设置
- while(1)
- {
- KeyDriver();
- switch(MODE)
- {
- case 0 : Time_Show(); break;
- case 1 : DS1302_SetTime();LCD_Show_Button(); break;
- }
-
- }
- }
-
- void InterruptTimer0() interrupt 1
- {
- static unsigned int T0_Count = 0;
- TL0 = 0x18;
- TH0 = 0xFC;
- T0_Count++;
- if(T0_Count==500)
- {
- T0_Count = 0;
- TimeSetFlashFlag = !TimeSetFlashFlag;
- }
-
- KeyScan();
- }
-
相关阅读:
速领!最新最全的C6678+Kintex-7视频/高速AD开发案例合集来了,附上源码!
2023.10.21 关于 阻塞队列
H5页面获取用户位置信息方案及测试流程
栈和队列(详解)
ThreadLocal详解
centos8安装mysql报错
Linux常见的文件系统
阿里云消息团队创新论文被软件工程顶会 FM 2024 录用
02 数学软件与建模---MATLAB入门
opencv之VideoCapture与VideoWriter笔记
-
原文地址:https://blog.csdn.net/asty008/article/details/126447813