参考了在51黑电子论坛里查到了好几位坛友发表的P10LED屏,用STC来驱动的帖子,其主要参考了未署名的一位网友的程序,在此表示感谢!
本帖子中采用了STC89C52作为MCU,DS3231作为时钟源,P10LED屏作为显示屏,显示效果如下几图和一个短视频。在这里值得一提的是P10供电电源问题,标准供电电压为5V,由于是远距离观看屏显示,在室内观看时亮度太高,非常刺眼,最关键是非常耗电,经过试验,把供电电压高低到2.3V左右就可以了,且电流只100MA左右,用普通的手机充电器供电都完全可以了。我再蒙上一层半透光的膜片效果更好了。
制作出来的实物图如下:
程序文件:
- #include <reg52.h>
- #include <intrins.h>
- //#define uchar unsigned char
- //#define uint unsigned int
- #define NOP _nop_()
- #define u8 unsigned char
- #define u16 unsigned int
- sbit OE = P2^0; //P10
- sbit A1 = P2^1; //P10
- sbit B1 = P2^2; //P10
- sbit SHCP=P2^4; //P10 11脚SHCP 移位时钟
- sbit STCP=P2^3; //P10 12脚STCP 锁存时钟
- sbit DATA=P2^5; //P10 数据输入
- //时钟DS3231接口
- sbit DSSDA =P2^7;//接时钟DS3231的SDA脚于P2.7
- sbit DSSCL=P2^6; //接时钟DS3231的SCL脚于P2.6
- sbit LED=P1^2; //定义LED端口
- //sbit LED1=P1^3;
- sbit SHEZ=P3^7; //设置键,从年、月、日、周、时、分、秒顺序移动;键值1-7
- sbit JIA=P3^6; //设置键值为1-7时,对应值加1;
- sbit JIAN=P3^5; //设置键值为1-7时,对应值减1;
- sbit QUED=P3^4; //完成设置后,使设置键的键值为0,保存到DS3231,完成时间的修改
- u8 code shisu[28][8]= //时钟数字
- {
- {0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38},//0
- {0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x3c},//1
- {0x00,0x38,0x44,0x44,0x08,0x10,0x20,0x7c},//2
- {0x00,0x38,0x44,0x04,0x18,0x04,0x44,0x38},//3
- {0x00,0x08,0x18,0x28,0x48,0x7c,0x08,0x08},//4
- {0x00,0x7c,0x40,0x78,0x04,0x04,0x44,0x38},//5
- {0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x38},//6
- {0x00,0x7c,0x44,0x08,0x10,0x10,0x10,0x10},//7
- {0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38},//8
- {0x00,0x38,0x44,0x44,0x3c,0x04,0x44,0x38},//9
- {0x20,0x3c,0x48,0x3c,0x28,0x7e,0x08,0x08},//10年
- {0x00,0x3e,0x22,0x3e,0x22,0x3e,0x22,0x46},//11月
- {0x00,0xfe,0x92,0xba,0xfe,0xba,0xaa,0xba},//12周
- {0x00,0x02,0xe2,0xaf,0xe2,0xaa,0xe2,0x06},//13时
- {0x00,0x28,0x24,0x42,0xbc,0x14,0x24,0x4c},//14分
- {0x00,0x74,0x2e,0xf5,0x26,0x74,0xa8,0x30},//15秒
- {0x00,0x00,0x00,0x02,0x7f,0x00,0x00,0x00},//16一
- {0x00,0x00,0x3c,0x00,0x00,0x00,0x7e,0x00},//17二
- {0x00,0x00,0x3c,0x00,0x3c,0x00,0x7e,0x00},//18三
- {0x00,0xfe,0xaa,0xaa,0xaa,0xce,0x82,0xfe},//19四
- {0x00,0x3c,0x10,0x10,0x3c,0x14,0x24,0x7e},//20五
- {0x00,0x20,0x10,0x7c,0x00,0x28,0x44,0x00},//21 六
- {0x00,0x3e,0x22,0x22,0x3e,0x22,0x22,0x3e},//22日
- {0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00},//23 :
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //24 无显示
- {0x00,0x60,0x6c,0x12,0x10,0x10,0x12,0x0c}, //25℃
- {0x00,0x00,0xf8,0x20,0x22,0x20,0x22,0x20}, //26 T:
- {0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00} //27 -
- };
- u8 code shisuz[4][8]= //十位数
- {
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //0
- {0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20}, //1
- {0x00,0xc0,0x20,0x20,0x60,0x80,0x80,0x60}, //2
- {0x00,0xc0,0x20,0x20,0xc0,0x20,0x20,0xc0} //3
- };
- u8 code shisuy[10][8]= //个位数
- {
- {0x00,0x06,0x09,0x09,0x09,0x09,0x09,0x06},//0
- {0x00,0x02,0x06,0x02,0x02,0x02,0x02,0x07},//1
- {0x00,0x06,0x09,0x09,0x01,0x02,0x04,0x0f},//2
- {0x00,0x06,0x09,0x01,0x06,0x01,0x09,0x06},//3
- {0x00,0x02,0x06,0x0a,0x0a,0x0f,0x02,0x02},//4
- {0x00,0x0f,0x08,0x0e,0x01,0x01,0x09,0x06},//5
- {0x00,0x06,0x09,0x08,0x0e,0x09,0x09,0x06},//6
- {0x00,0x0f,0x09,0x02,0x02,0x02,0x02,0x02},//7
- {0x00,0x06,0x09,0x09,0x06,0x09,0x09,0x06},//8
- {0x00,0x06,0x09,0x09,0x07,0x01,0x09,0x06},//9
- };
- u8 table1[2][32];//P10写屏变量
- u8 T[7]=0,hp=0,js=0,sz,tt; //定义时间变量:秒、分、时、周、日、月、年;换屏变量,温度
- bit f; //定义温度符号
- void DS3231_IIC_delay(void); //延时函数
- void DS3231_IIC_start(void) ; //起始信号
- void DS3231_IIC_stop(void); //停止信号
- void DS3231_IIC_Tack(void); //接收应答
- void DS3231_IIC_write_byte(u8 Data); //写入一个字节的数据函数
- u8 DS3231_IIC_read_byte(void); //读取1个字节数据函数
- void DS3231_IIC_single_byte_write(u8 Waddr,u8 Data); //写入数据函数
- u8 DS3231_IIC_single_byte_read(u8 Waddr); //读取数据函数
- void DS3231_IIC_lianxu_read(void); //连续读取0H-06H中的数据
- void DS3231_IIC_Init(void); //初始化
- void Init_Timer0(void); //定时零提供秒闪
- void dushu(u8 n); //写数据
- void KEY(void); //按键函数
- void get_T(void); //温度获取
- /*******************************************************************************************/
- /*******************************************************************************************/
- void Delay1ms(u16 mm) //11.0592MHz
- {
- u8 i, j,k;
- _nop_();
- for(k=0;k<mm;k++)
- { i = 2;
- j = 199;
- do { while (--j); } while (--i);
- }
- }
- //P10数据串行输入
- void serial_input(u8 dat)
- {
- u16 m;
- for(m=0;m<8;m++)
- {
- if(dat & 0x80)
- DATA=0; //
- else
- DATA=1; //修改取反
- SHCP=0;
- SHCP=1;
- NOP;
- NOP;
- SHCP=0;
- NOP;
- NOP;
- dat=dat<<1;
- }
- }
- /*******************************************************************************************/
- //P10并出
- void serial_output()
- {
- STCP=1;
- NOP;
- NOP;
- STCP=0;
- }
- /*******************************************************************************************/
- /*******************************************************************************************/
- //P10行显控制
- void HC138_scan(u8 temp)
- {
- OE=1;
- A1=0x01 & temp;
- B1=0x01 &(temp>>1);
- }
- /*******************************************************************************************/
- //读取数字函数
- void dushu(u8 n) //参数0正常显示,参数1为设置
- {
- u8 i;
- if(n==0)
- {
- for(i=0;i<8;i++)
- table1[0][2*i]=shisu[T[2]>>4][i];//上部 0
- for(i=0;i<8;i++)
- if(LED==1) table1[0][2*i+1]=shisu[T[2]&0x0f][i]|shisu[23][i];
- else table1[0][2*i+1]=shisu[T[2]&0x0f][i];//上部 1|shisuz[2][i]
- for(i=0;i<8;i++)
- table1[1][2*i]=shisu[T[1]>>4][i];//上部 2
- for(i=0;i<8;i++)
- table1[1][2*i+1]=shisu[T[1]&0x0f][i];//上部 3
- switch(hp)
- {
- case 0:{
- for(i=8;i<16;i++)
- table1[0][2*i]=shisuz[T[6]>>4][i-8]|shisuy[T[6]&0x0f][i-8]; //下部 0
- for(i=8;i<16;i++)
- table1[0][2*i+1]=shisu[10][i-8]; //下部 1 年字
- for(i=8;i<16;i++)
- table1[1][2*i]=shisuz[T[5]>>4][i-8]|shisuy[T[5]&0x0f][i-8]; //下部 2 周字
- for(i=8;i<16;i++)
- table1[1][2*i+1]=shisu[11][i-8]; //下部 3 月
- }
- break; //显示年月
- case 1:{
- for(i=8;i<16;i++)
- table1[0][2*i]=shisuz[T[4]>>4][i-8]|shisuy[T[4]&0x0f][i-8]; //下部 0
- for(i=8;i<16;i++)
- table1[0][2*i+1]=shisu[22][i-8]; //下部 1 日字
- for(i=8;i<16;i++)
- table1[1][2*i]=shisu[12][i-8]; //下部 2 周字
- for(i=8;i<16;i++)
- table1[1][2*i+1]=shisu[T[3]+15][i-8]; //下部 3
- }
- break; //显示日和星期
- case 2:{
- get_T(); //首先获取温度
- if(f==0)
- for(i=8;i<16;i++)
- table1[0][2*i]=shisu[26][i-8]; //下部 首位显示T:
- else
- for(i=8;i<16;i++)
- table1[0][2*i]=shisu[27][i-8]; //下部首位显示-
- for(i=8;i<16;i++)
- table1[0][2*i+1]=shisu[tt/10][i-8]; //下部 1
- for(i=8;i<16;i++)
- table1[1][2*i]=shisu[tt%10][i-8]; //下部 2
- for(i=8;i<16;i++)
- table1[1][2*i+1]=shisu[25][i-8]; //下部 3
- }
- break; //显示温度
- }
- }
- else
- {
- /********************设置日期时上半部分显示内容*************************************/
- switch(sz)
- {
- case 1:{ //修改年份
- for(i=0;i<8;i++)
- table1[0][2*i]=shisu[T[6]/10][i];//上部 0 年的十位,不闪烁
- for(i=0;i<8;i++)
- if(LED==1) table1[0][2*i+1]=shisu[T[6]%10][i];
- else table1[0][2*i+1]=shisu[24][i];//上部 1
- for(i=0;i<8;i++)
- table1[1][2*i]=shisu[10][i];//上部 2 显示年
- for(i=0;i<8;i++)
- table1[1][2*i+1]=shisu[24][i];//上部 3 不显示
- }
- break;
- case 2:{ //修改月份
- for(i=0;i<8;i++)
- table1[0][2*i]=shisu[T[5]/10][i];//上部 0 月的十位,不闪烁
- for(i=0;i<8;i++)
- if(LED==1) table1[0][2*i+1]=shisu[T[5]%10][i];
- else table1[0][2*i+1]=shisu[24][i];//上部 1
- for(i=0;i<8;i++)
- table1[1][2*i]=shisu[11][i];//上部 2 显示月
- for(i=0;i<8;i++)
- table1[1][2*i+1]=shisu[24][i];//上部 3 不显示
- }
- break;
- case 3:{ //修改日期
- for(i=0;i<8;i++)
- table1[0][2*i]=shisu[T[4]/10][i];//上部 0 日的十位,不闪烁
- for(i=0;i<8;i++)
- if(LED==1) table1[0][2*i+1]=shisu[T[4]%10][i];
- else table1[0][2*i+1]=shisu[24][i];//上部 1
- for(i=0;i<8;i++)
- table1[1][2*i]=shisu[22][i];//上部 2 显示日
- for(i=0;i<8;i++)
- table1[1][2*i+1]=shisu[24][i];//上部 3 不显示
- }
- break;
- case 4:{ //修改星期
- for(i=0;i<8;i++)
- table1[0][2*i]=shisu[24][i];//上部 0 星期的十位,不显示
- for(i=0;i<8;i++)
- if(LED==1) table1[0][2*i+1]=shisu[T[3]][i];
- else table1[0][2*i+1]=shisu[24][i];//上部 1|shisuz[2][i]
- for(i=0;i<8;i++)
- table1[1][2*i]=shisu[12][i];//上部 2 显示周
- for(i=0;i<8;i++)
- table1[1][2*i+1]=shisu[24][i];//上部 3 不显示
- }
- break;
- case 5:{ //修改小时
- for(i=0;i<8;i++)
- table1[0][2*i]=shisu[T[2]/10][i];//上部 0 小时的十位,不闪烁
- for(i=0;i<8;i++)
- if(LED==1) table1[0][2*i+1]=shisu[T[2]%10][i];
- else table1[0][2*i+1]=shisu[24][i];//上部 1|shisuz[2][i]
- for(i=0;i<8;i++)
- table1[1][2*i]=shisu[13][i];//上部 2 显示时
- for(i=0;i<8;i++)
- table1[1][2*i+1]=shisu[24][i];//上部 3 不显示
- }
- break;
- case 6:{ //修改分钟
- for(i=0;i<8;i++)
- table1[0][2*i]=shisu[T[1]/10][i];//上部 0 分钟的十位,不闪烁
- for(i=0;i<8;i++)
- if(LED==1) table1[0][2*i+1]=shisu[T[1]%10][i];
- else table1[0][2*i+1]=shisu[24][i];//上部 1|shisuz[2][i]
- for(i=0;i<8;i++)
- table1[1][2*i]=shisu[14][i];//上部 2 显示分
- for(i=0;i<8;i++)
- table1[1][2*i+1]=shisu[24][i];//上部 3 不显示
- }
- break;
- case 7:{ //修改秒钟
- for(i=0;i<8;i++)
- table1[0][2*i]=shisu[T[0]/10][i];//上部 0 秒的十位,不闪烁
- for(i=0;i<8;i++)
- if(LED==1) table1[0][2*i+1]=shisu[T[0]%10][i];
- else table1[0][2*i+1]=shisu[24][i];//上部 1|shisuz[2][i]
- for(i=0;i<8;i++)
- table1[1][2*i]=shisu[15][i];//上部 2 显示秒
- for(i=0;i<8;i++)
- table1[1][2*i+1]=shisu[24][i];//上部 3 不显示
- }
- break;
- }
-
- /*************设置日期时下部均不显示************************/
- for(i=8;i<16;i++)
- table1[0][2*i]=shisu[24][i-8]; //下部 0
- for(i=8;i<16;i++)
- table1[0][2*i+1]=shisu[24][i-8]; //下部 1
- for(i=8;i<16;i++)
- table1[1][2*i]=shisu[24][i-8]; //下部 2
- for(i=8;i<16;i++)
- table1[1][2*i+1]=shisu[24][i-8]; //下部 3
- }
- }
- /*******************************************************************************************/
- //P10整屏显示
- void display(void)
- {
- u8 i,j,k;
- for(k=0;k<4;k++) //显示的四行
- {
- for(j=0;j<2;j++) //显示3、4列
- {
- for(i=0;i<2;i++) // 显示1、2列
- {
-
- serial_input(table1[j][3*8+2*k+i]);
- serial_input(table1[j][2*8+2*k+i]);
- serial_input(table1[j][1*8+2*k+i]);
- serial_input(table1[j][0*8+2*k+i]);
- }
- }
- serial_output();
- HC138_scan(k);
- }
- }
- /*******************************************************************************************/
- /*******************************************************************************************/
- /*******************************************************************************************/
- /*******************************************************************************************/
- void main()
- {
- // u8 i, Waddr=0;
- Init_Timer0();
- Delay1ms(1);
- DS3231_IIC_Init();
- /* T[0]=0x00; //0秒
- T[1]=0x01; //50分
- T[2]=0x22; //23点
- T[3]=0x05; //星期日
- T[4]=0x07; //7日
- T[5]=0x05; //5月
- T[6]=0x21; //21年
- for(i=0;i<7;i++) //写入日期和时间
- {
- DS3231_IIC_single_byte_write(Waddr,T[i]);
- Waddr++;
- } */
- Delay1ms(2);
- //display();
- DS3231_IIC_lianxu_read(); //连续读取0H-06H中的数据
- Delay1ms(2);
- dushu(0);
- while(1)
- {
- /* if(LED==1)
- {
- DS3231_IIC_lianxu_read(); //连续读取0H-06H中的数据
- dushu();
- }*/
- display(); //显示
- KEY(); //键盘扫描
- if(sz!=0) dushu(1);
- /*Delay1ms();
- Delay1ms();
- Delay1ms();
- Delay1ms(); */
- }
- }
- void DS3231_IIC_delay(void) //延时函数
- {
- u8 i;
- for(i=0;i<1;i++);
- }
- void DS3231_IIC_start(void) //起始信号
- {
- DSSDA=1;
- DSSCL=1;
- DS3231_IIC_delay();
- DSSDA=0;
- DS3231_IIC_delay();
- DSSCL=0;
- }
- void DS3231_IIC_stop(void) //停止信号
- {
- DSSDA=0;
- DS3231_IIC_delay();
- DSSCL=1;
- DS3231_IIC_delay();
- DSSDA=1;
- DS3231_IIC_delay();
- }
- void DS3231_IIC_Tack(void) //接收应答
- {
- DSSCL=1; //拉高SCL
- DS3231_IIC_delay();
- while(DSSDA==1); //由P2.7读入1,表示3231无应答,需要等待
- DS3231_IIC_delay();
- DSSCL=0; //拉低SCL
- DS3231_IIC_delay();
- }
- void DS3231_IIC_write_byte(u8 Data) //写入一个字节的数据函数
- {
- u8 i;
- for (i=0;i<8;i++)
- {
- if(Data&0x80)
- DSSDA=1;
- else
- DSSDA=0;
- DS3231_IIC_delay();
- DSSCL=1;
- DS3231_IIC_delay();
- DSSCL=0;
- DS3231_IIC_delay();
- Data=Data<<1;
- }
- }
- u8 DS3231_IIC_read_byte(void) //读取1个字节数据函数
- {
- u8 i,Data;
- for(i=0;i<8;i++)
- {
- DSSCL=1;
- DS3231_IIC_delay();
- Data=Data<<1;
- DS3231_IIC_delay();
- if(DSSDA)
- Data=Data|0x01;
- DSSCL=0;
- DS3231_IIC_delay();
- }
- return Data;
- }
- void DS3231_IIC_single_byte_write(u8 Waddr,u8 Data) //写入数据函数
- {
- DS3231_IIC_start();
- DS3231_IIC_write_byte(0xd0);//DS3231的地址
- DS3231_IIC_Tack();
- DS3231_IIC_write_byte(Waddr);//欲写入的地址
- DS3231_IIC_Tack();
- DS3231_IIC_write_byte(Data);//欲写入的地址数据
- DS3231_IIC_Tack();
- DS3231_IIC_stop();
- }
- u8 DS3231_IIC_single_byte_read(u8 Waddr) //读取数据函数
- {
- u8 Data;
- DS3231_IIC_start();
- DS3231_IIC_write_byte(0xd0);//DS3231的地址
- DS3231_IIC_Tack();
- DS3231_IIC_write_byte(Waddr);//欲读取的地址,本质上是移动指针
- DS3231_IIC_Tack();
- DS3231_IIC_stop();
- DS3231_IIC_start();
- DS3231_IIC_write_byte(0xd1);//告诉3231欲读取指针所指寄存器内容
- DS3231_IIC_Tack();
- Data=DS3231_IIC_read_byte();
- DS3231_IIC_delay();
- DS3231_IIC_stop();
- return Data;
- }
- void DS3231_IIC_lianxu_read(void) //连续读取0H-06H中的数据
- {
- u8 i,Waddr;
- Waddr=0x00;
- for(i=0;i<7;i++)
- {
- T[i]=DS3231_IIC_single_byte_read(Waddr);
- Waddr=Waddr+1;
- }
- }
- void DS3231_IIC_Init(void) //初始化
- {
- DSSDA=1;
- DSSCL=1;
- DS3231_IIC_single_byte_write(0x0e,0x00);
- }
- /*********温度获取***************/
- void get_T(void)
- {
- u8 Tem_L,Tem_H;
- Tem_H=DS3231_IIC_single_byte_read(0x11); //温度 高字节 整数部分
- Tem_L=DS3231_IIC_single_byte_read(0x12); //温度 低字节 小数部分
-
- Tem_L = (Tem_L>>6)*0.25+0.5; //小数部分四舍五入
- tt=Tem_H+Tem_L;
- f=Tem_H>>7 ; //是1的话表示负温度,0为正温度
- }
- /*------------------------------------------------
- 定时器初始化子程序
- ------------------------------------------------*/
- void Init_Timer0(void)
- {
- TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
- //TMOD |= 0x11;
- TH0=(65536-2000)/256; //给定初值 2毫秒
- TL0=(65536-2000)%256;
- EA=1; //总中断打开
- ET0=1; //定时器中断打开
- TR0=1; //定时器开关打开
- /*TMOD |= 0x10; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
- TH1=0x00; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
- TL1=0x00;
- //EA=1; //总中断打开
- ET1=1; //定时器中断打开
- TR1=1; //定时器开关打开
- IT1=1;*/
- }
- /*------------------------------------------------
- 定时器中断子程序
- ------------------------------------------------*/
- void Timer0_isr(void) interrupt 1 //using 1
- {
- static unsigned char num;
- TH0=(65536-2000)/256; //重新赋值 2毫秒
- TL0=(65536-2000)%256;
- num++;
- if(num==250)
- {
- num=0;
- js++;
- LED=~LED; //指示灯反相,可以看到闪烁
- if(sz==0)
- {
- dushu(0);
- if(js==10)
- {
- js=0;
- hp++;
- if(hp==3) hp=0;
- DS3231_IIC_lianxu_read(); //连续读取0H-06H中的数据
-
- }
- }
- /*display();
- */
-
- }
- }
- /*
- //外部中断解码程序
- void intersvr1(void) interrupt 2 using 1
- {
- LED1=~LED1; //LED1闪烁
-
- }
- */
- /*------------------------------------------------
- 定时器中断子程序
- ------------------------------------------------
- void Timer1_isr(void) interrupt 3 using 1
- {
- TH1=(65536-2000)/256; //重新赋值
- TL1=(65536-2000)%256;
- ss++;
- if(ss==250)
- {
- ss=0;
- LED=~LED; //LED闪烁
- }
- }*/
- void KEY(void) //按键函数
- {
- u8 i,ss,Waddr=0;
- if(SHEZ==0)
- {
- Delay1ms(15);
- if(SHEZ==0) //如果没有按下就跳出
- {
- while(!SHEZ); //等待按键松开
- sz++;
- if(sz==1)
- for(i=0;i<7;i++)
- T[i]=(T[i]>>4)*10+(T[i]&0x0f) ; //将BCD十六进制数转化为十进制数
- if(sz==8) sz=1;
- }
- }
- if(JIA==0) //加1键
- {
- Delay1ms(15);
- if(JIA==0) //如果没有按下就跳出
- {
- while(!JIA); //等待按键松开
- switch(sz)
- {
- case 1:{
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
完整程序请下载附件:
P10_DS3231.rar
(8.7 KB, 下载次数: 110)
|