注:本人大一新生,未学习电路,单片机,C语言,汇编均为自学内存,故难免有所疏露,希望大家多多指点。
该项目为惠州学院计算机系嵌入式培训班硬件组的任务(本人是电子系的,但还是加入了呵)。
设计思路:
1,确定电路模型。
2,写源程序。
3,调试。
项目名称:基于PROTEUS仿真的16*64点阵屏
关键字:16,64,点阵,PROTEUS,DS1302,74HC595。
元器件使用清单 | |||||||
AT89S52*1 | 无源晶振33MHz*1 | 无源晶振32.768KHz | 电容33pF*2 | 电容10uF*1 | 限流电阻10K*1 | 复位式按键开关*1 | 钮扣电池3V*1 |
74HC595 | DS1302 | 74HC154 | 8*8LED点阵 |
实现思路:
最小系统就不讲了,由于扫描次数多,故晶振频率要高,避免抖动。
首先,讲级联,这是我最最头痛的事了。在网下载了几份英文的中文的数据手册后,便开始了有道之旅,看完了整份英文版的数据手册后我有了想把74595翻译成中文的欲望。为什么?因为我觉得我能把它翻译得比百度上面的好呵呵,开玩笑的。嗯,请看74595的原理图。
芯片简介:The HC595A consists of an 8–bit shift register and an 8–bit D–type latch with three–state parallel outputs. The shift register accepts serial data and provides a serial output. The shift register also provides parallel data to the 8–bit latch. The shift register and latch have independent clock inputs. This device also has an asynchronous reset for the shift register.
HC595A包含了一个8位的移位寄存器和一个8位3态并行输出的D类型锁存器。移位寄存器通过串行数据输入(SERIAL DATA INPUT)接收串行数据,并附有一个串行数据输出口(SERIAL DATA OUTPUT)用于级联。移位寄存器提供并行数据给8位锁存器。两个寄存器有着独立的时钟脉冲输入。该器件的移位寄存器也有一个异步复位引脚。
数据手册中很多表,那都是很有用的,因为那些参数关系到一个产品的稳定性等。但对于大一的我,就只是半懂不懂的略看了一下,说不拿出来说了哈,因为还没学电路和模电。
PIN DESCRIPTIONS
INPUTS
A (Pin 14)
Serial Data Input. The data on this pin is shifted into the
8–bit serial shift register.
CONTROL INPUTS
Shift Clock (Pin 11)
Shift Register Clock Input. A low– to–high transition on this
input causes the data at the Serial Input pin to be shifted into
the 8–bit shift register.
Reset (Pin 10)
Active–low, Asynchronous, Shift Register Reset Input. A
low on this pin resets the shift register portion of this device
only. The 8–bit latch is not affected.
Latch Clock (Pin 12)
Storage Latch Clock Input. A low–to–high transition on this
input latches the shift register data.
Output Enable (Pin 13)
Active–low Output Enable. A low on this input allows the
data from the latches to be presented at the outputs. A high
on this input forces the outputs (QA–QH) into the high–
impedance state. The serial output is not affected by this
control unit.
OUTPUTS
QA – QH (Pins 15, 1, 2, 3, 4, 5, 6, 7)
Noninverted, 3–state, latch outputs.
SQH (Pin 9)
Noninverted, Serial Data Output. This is the output of the
eighth stage of the 8–bit shift register. This output does not
have three–state capability.
翻译:
A:毫无疑问,是数据输入引脚。
Shift Clock:移位寄存器时钟脉冲输入引脚,给该引脚一个上升沿(低电平变化成高电平),数据(一位)将从A引脚读入移位寄存器,怎么实现的呢?首先,将原来的寄存器的里二进制数据移位SRn---->SRn+1,并且把SRH的数据通过SERIAL DATA OUTPUT输出(可以被下一个595的A读取,从而实现级联)。
RESET:复位就说了吧。一个低电平就可以了。
LATCH CLOCK:锁存器时钟脉冲,给它一个上升沿,移位寄存器里的数据将输入到LATCH寄存器里面去,如果OUTPUT ENABLE输入使能端为低电平,数据将通过LATCH输出。
注:移位寄存器时钟脉冲变化与内置锁存器脉冲的变化时独立的,即没影响。
好了,讲完了引脚,那么上级联的图片(PROTEUS)吧。
嗯这就是级联图,怎么样?是不是和网上其他人的一样,对!我就是参考别人的哈。
接下来,请看74154——一个4对16的译码器的真值表,这个译码器采用压缩BCD码(具体请百度)。
怎么用应该知道了吧,就是我给A0~A3一个压缩BCD码值,它的16个输出引脚将输出上面真值表的值。很显然,每次只有一个引脚输出低电平。
嗯,我是能过级联,给595一个64个位的数据,再驱动154选中一行,点亮图型的一行,如此循环,就显示出了图形,时间,数字等。
好了,讲讲DS1302吧。
DS1302:
The DS1302 trickle-charge timekeeping chip contains a real-time clock/calendar and 31 bytes of static RAM.
我的翻译:DS1302是一个带涓流充电的时间记录芯片,它包含了一个实时时钟/日历和大小为31字节的RAM。
这里,我插入DS1302的引脚图(来自MAXIM DS1302)
嗯,讲下引脚吧,X1,X2(XTAL)接一个32.768KHz的晶振,这里,需要强调的有以下来自DATASHEET中的一句话。
“The DS1302 uses an external 32.768kHz crystal. The oscillator circuit does not require any external resistors or capacitors to operate.”
从这句话可以知,DS1302的晶振电路是不需要电容的,在网上下载(百度中“DS1302中文资料”第一篇)的数据手册的接线图是错的呵,
原作者在该晶振中接了6PF的电容(可能他不小心看错了吧),这个表的意思是该晶振具有6PF的负载容抗应该,因为DS1302内部己经集成了
电容了呵呵。
VCC1连接一个3V的备用电源的正极。
VCC2正常情况下连接大于3.2V的主供应电源。
CE:老版本的数据手册里面为RESET(复位),为什么换名了呢?这应该是DS1302新增了“突发/爆发模式”的原故吧,我觉得。
CE有两个作用:其一,打开如Figure1图中逻辑控制器,使移位寄存器能接收指令或地址。其二,提供一种终止结束单/多字节数据传输的方法。
在输出/输入数据时,该引脚必须为高电平。注意:在开始数据传输时,SCLK引脚必须为0(低电平)时才能把CE拉至1(高电平)。在一个字
节的数据传输完时,如是CE还保持高电平,则启动突发模式,即可以连续读/写时间/日历寄存器,或连续读/写31个字节的RAM。
插一下与DS1302通迅的“协议”哈。
DS1302的输出/输入只有一个脚啊!怎么与它通讯呢?——串口通讯。
与DS1302通讯前,先发一条COMMAND,然后再执行相应的读写操作。
在上表中,第0位控制读/写,显然,bit0=0时为写操作,A0~A4为对应的操作数(地址),2^5=32>31(RAM内存)。而bit6为你要操作的对象,是RAM还是
DS1302的时钟/日历寄存器?而最高位MSB(即bit7,英文为most significant bit),正常情况下为1,为0的话,DS1302停止工作。
好了,讲回引脚吧,I/O显然是通讯引脚,而SCLK来头比较大些,下面详讲。
SCLK:当SCLK在上升沿时,DS1302移位寄存器读入指令(command)一个位。下降沿时,DS1302输出时间/日历/数据/的一个位。无论读出读入,都是从bit0
开始的。嗯,也就是说,给DS1302传指令需要一位一位的传,传一个bit的同时SCLK要上升沿,而读时每读一个字节前要制造一个下降沿。另外,还有一点要注意的是,
若传输的是读指令,读出数据/时间将在读指令最后一位输入后的第一个下降沿输出。程序写不好的话会造成读出数据不准(见下图)。另外,再声明一次,DS1302中,时钟/日历
寄存器中的数据是用压缩BCD码表示的。读出写入时间/日历都应做相应的转换。(见下)
写入的时间/日期可用一个宏来实现:#define BCD(time) (time/10*16+time%10) //定义宏,将要写入DS1302的时间转化为BCD码
而读出呢?反过来思考下就行了哈哈。
指令(COMMAND)数据手册已经详细给出了。就是数据手册Table 3. Register Address/Definition里面的READ/和WRITE里面的数据,RAM同理在下面有给出。
这是我写的驱动程序(仅供参考,可能有误):
/*************************************************************************************** * File Name: 74HC595驱动程序 * Effect: 驱动74HC595 * Head: 74HC595.h * Explaination: 函数ShiftReg用于输出一个8个位的数据; * 函数ShiftMove用于输出一个位的后mov位; * 函数ShiftAdd用于输一个数据的前mov位; * 函数OE_595用于控制74595的输出使能端; * 函数Init595用于初使化74595; * 函数LoadLatch用于将shift register中的数据装载进Latch register. * Author: Mason * 别名: 小菜 * Email Address: 1609099954@qq.com * last modified time:2012-7-25 * Performance:Finished * Question: **************************************************************************************/ #include<reg52.h> #include"drive595.h" sbit OUTEN =P1^0; //Connected OUTEN to OutputEnable of 74HC595 sbit RESET74595 =P1^1; //Reset sbit LCLK =P1^2; //Latch Clock sbit SCLK =P1^3; //Serial Clock sbit SDIN =P1^4; //Serial Data Input extern void ShiftReg(unsigned char TranChar) //函数ShiftReg用于输出一个8个位的数据 { unsigned char z; for(z=0;z<8;z++) { ((TranChar&0x80)!=0x00)?(SDIN=1):(SDIN=0); SCLK=1; //上升沿:使SDIN数据读入Shift Register TranChar<<=1; SCLK=0; } } extern void Shiftmove(unsigned char TranChar,unsigned mov) { //函数ShiftMove用于输出一个位的后mov位 unsigned char z; TranChar<<=mov; for(z=0;z<7-mov;z++) { ((TranChar&0x80)!=0x00)?(SDIN=1):(SDIN=0); SCLK=1; //rising edge:使SDIN数据读入Shift Register TranChar<<=1; SCLK=0; } } extern void Shiftadd(unsigned char TranChar,unsigned mov) { //函数ShiftAdd用于输一个数据的前mov位 unsigned char z; for(z=0;z<mov;z++) { ((TranChar&0x80)!=0x00)?(SDIN=1):(SDIN=0); SCLK=1; //rising edge:使SDIN数据读入Shift Register TranChar<<=1; SCLK=0; } } extern void OE_595(char flag) //该函数用于控制输出使能端 { OUTEN=flag; } extern void LoadLatch(void) { LCLK=1; //上升沿:使Latch最后一位数据通过级连传给下一595 LCLK=0; } extern void Init595(void) { RESET74595=1; OUTEN=1; LCLK=0; //Serial data input SCLK=0; //Serial clock } extern void Reset595(void) //复位74HC595 { RESET74595=0; RESET74595=1; }
/*************************************************************************************** * File Name: 74HC595驱动程序头文件 * Effect: 声名外部函数 * Head: 74HC595.h * Explaination: 函数ShiftReg用于输出一个8个位的数据; * 函数ShiftMove用于输出一个位的后mov位; * 函数ShiftAdd用于输一个数据的前mov位; * 函数OE_595用于控制74595的输出使能端; * 函数Init595用于初使化74595; * 函数LoadLatch用于将shift register中的数据装载进Latch register. * Author: Mason * 别名: 小菜 * Email Address: 1609099954@qq.com * last modified time:2012-7-22 * Performance: Finished * Question: **************************************************************************************/ #ifndef DRIVE595_H #define DRIVE595_H extern void ShiftReg(unsigned char TranChar); //向74595传输TranChar 的8个位 extern void Shiftmove(unsigned char TranChar,unsigned mov); //向74595传输TranChar 的后move 个位 extern void Shiftadd(unsigned char TranChar,unsigned mov); //向74959传输TranChar 的前move 个位 extern void OE_595(char flag); //flag=0,禁止输出;flag=1,允许输出 extern void Init595(void); //初使化74595 extern void LoadLatch(void); //将shift register中的数据装载进Latch register,若flag=0则数据输出。 extern void Reset595(void); //复位74595 #endif
/*************************************************************************************** * File Name: 74HC595驱动程序 * Effect: 驱动74HC595 * Head: 74HC595.h * Explaination: 函数ShiftReg用于输出一个8个位的数据; * 函数ShiftMove用于输出一个位的后mov位; * 函数ShiftAdd用于输一个数据的前mov位; * 函数OE_595用于控制74595的输出使能端; * 函数Init595用于初使化74595; * 函数LoadLatch用于将shift register中的数据装载进Latch register. * Author: Mason * 别名: 小菜 * Email Address: 1609099954@qq.com * last modified time:2012-7-25 * Performance:Finished * Question: **************************************************************************************/ #include<reg52.h> #include"drive595.h" sbit OUTEN =P1^0; //Connected OUTEN to OutputEnable of 74HC595 sbit RESET74595 =P1^1; //Reset sbit LCLK =P1^2; //Latch Clock sbit SCLK =P1^3; //Serial Clock sbit SDIN =P1^4; //Serial Data Input extern void ShiftReg(unsigned char TranChar) //函数ShiftReg用于输出一个8个位的数据 { unsigned char z; for(z=0;z<8;z++) { ((TranChar&0x80)!=0x00)?(SDIN=1):(SDIN=0); SCLK=1; //上升沿:使SDIN数据读入Shift Register TranChar<<=1; SCLK=0; } } extern void Shiftmove(unsigned char TranChar,unsigned mov) { //函数ShiftMove用于输出一个位的后mov位 unsigned char z; TranChar<<=mov; for(z=0;z<7-mov;z++) { ((TranChar&0x80)!=0x00)?(SDIN=1):(SDIN=0); SCLK=1; //rising edge:使SDIN数据读入Shift Register TranChar<<=1; SCLK=0; } } extern void Shiftadd(unsigned char TranChar,unsigned mov) { //函数ShiftAdd用于输一个数据的前mov位 unsigned char z; for(z=0;z<mov;z++) { ((TranChar&0x80)!=0x00)?(SDIN=1):(SDIN=0); SCLK=1; //rising edge:使SDIN数据读入Shift Register TranChar<<=1; SCLK=0; } } extern void OE_595(char flag) //该函数用于控制输出使能端 { OUTEN=flag; } extern void LoadLatch(void) { LCLK=1; //上升沿:使Latch最后一位数据通过级连传给下一595 LCLK=0; } extern void Init595(void) { RESET74595=1; OUTEN=1; LCLK=0; //Serial data input SCLK=0; //Serial clock } extern void Reset595(void) //复位74HC595 { RESET74595=0; RESET74595=1; }
/***************************************************************************** * File Name: 16_64点阵驱动程序.c * Effect: 基于proteus仿真软件的程序,可驱动16*64点阵屏 * * Explaination: Fosc=33MHz * Author: Mason * 别名: 小菜 * Email Address: 1609099954@qq.com * last modified time:2012-7-25 * Performance: Finished * Question: *****************************************************************************/ #include<reg52.h> #include"drive595.h" #include"ds1302.h" #include"display.h" #define uint unsigned int #define uchar unsigned char #define BCD(time) (time/10*16+time%10) //定义宏,将要写入DS1302的时间转化为BCD码 /**************************DS1302指令定义*************************************/ #define Write_Sec 0x80 #define Write_Min 0x82 #define Write_Hou 0x84 #define Write_Dat 0x86 #define Write_Mon 0x88 #define Write_day 0x8a #define Write_Yea 0x8c #define Write_WP 0x8e //写保护位 #define Write_TCR 0x90 //涓流充电寄存器写指令 #define Read_Sec 0x81 #define Read_Min 0x83 #define Read_Hou 0x85 #define Read_Dat 0x87 #define Read_Mon 0x89 #define Read_Day 0x8b #define Read_Yea 0x8d #define CLK_BurstW 0xbf //时钟突发模式写 #define CLK_BurstR 0xbf //时钟突发模式读 #define Write_RAM_Begin 0xc0 //RAM第一个字节写指令 #define Read_RAM_Begin 0xc1 //RAM第一个字节读指令 #define RAM_BurstW 0xfe //突发模式写RAM #define RAM_BurstR 0xff //突发模式读RAM /*****************************变量定义*******************************/ uchar shiftime=0,number=0,move=0; //shiftime控制移动时间,number 用于控制显示的字,move 用于移动显示效果 uchar words=43; //为con_move提供二维组数matrix的第一维长度 uchar* idata timetable[45]; //该数组用于存储指向要显示的字模的指针。 /*****************************字型码*********************************/ uchar code matrix[][16]={ {0x00,0x00,0x00,0x1E,0x36,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00},/*"0"*/ {0x00,0x00,0x00,0x18,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00},/*"1"*/ {0x00,0x00,0x00,0x3E,0x43,0x03,0x03,0x06,0x0C,0x18,0x20,0x7F,0x00,0x00,0x00,0x00},/*"2"*/ {0x00,0x00,0x00,0x7C,0x46,0x06,0x06,0x38,0x06,0x06,0x46,0x7C,0x00,0x00,0x00,0x00},/*"3"*/ {0x00,0x00,0x00,0x0E,0x0E,0x16,0x26,0x66,0x46,0xFF,0x06,0x06,0x00,0x00,0x00,0x00},/*"4"*/ {0x00,0x00,0x00,0x7E,0x60,0x60,0x7C,0x0E,0x06,0x06,0x4E,0x78,0x00,0x00,0x00,0x00},/*"5"*/ {0x00,0x00,0x00,0x1E,0x30,0x60,0x6E,0x73,0x63,0x63,0x33,0x1E,0x00,0x00,0x00,0x00},/*"6"*/ {0x00,0x00,0x00,0x7E,0x06,0x04,0x0C,0x08,0x18,0x18,0x10,0x30,0x00,0x00,0x00,0x00},/*"7"*/ {0x00,0x00,0x00,0x3E,0x63,0x63,0x36,0x1C,0x67,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},/*"8"*/ {0x00,0x00,0x00,0x1C,0x66,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00,0x00,0x00},/*"9"*/ {0x00,0x00,0x01,0x03,0x04,0x01,0x07,0x01,0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00},/*"年",10*/ {0x00,0xC8,0xF8,0x60,0x3C,0xE0,0x60,0x7F,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x00}, {0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x03,0x02,0x04,0x0C,0x10,0x00,0x00,0x00},/*"月",12*/ {0x00,0x00,0x78,0x98,0x18,0xD8,0x18,0xD8,0x18,0x18,0x18,0xD8,0x38,0x00,0x00,0x00}, {0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00},/*"日",14*/ {0x00,0x00,0x00,0x00,0xFC,0x8C,0x0C,0xEC,0x0C,0x0C,0xEC,0x1C,0x08,0x00,0x00,0x00}, {0x00,0x00,0x07,0x0C,0x0F,0x0C,0x0F,0x07,0x0C,0x1F,0x02,0x07,0x38,0x1F,0x00,0x00},/*"星",16*/ {0x00,0x00,0xE0,0x30,0x30,0x30,0xF0,0xE0,0x80,0xF8,0x80,0xF0,0x80,0xF8,0x0C,0x00}, {0x00,0x00,0x12,0x5A,0x3E,0x12,0x1A,0x1E,0x12,0x1A,0x3E,0x15,0x36,0x63,0x00,0x00},/*"期",18*/ {0x00,0x00,0x70,0x78,0xCC,0xFC,0xDC,0xCC,0xFC,0xDC,0x8C,0x8C,0xC8,0x38,0x00,0x00}, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"一",20*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, {0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x1F,0x20,0x00,0x00,0x00},/*"二",22*/ {0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x0C,0xFE,0x00,0x00,0x00,0x00}, {0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3F,0x00,0x00,0x00},/*"三",24*/ {0x00,0x00,0x00,0xF0,0x80,0x00,0x00,0x60,0x80,0x00,0x00,0x1C,0xE6,0x00,0x00,0x00}, {0x00,0x00,0x00,0x00,0x03,0x3E,0x3E,0x24,0x14,0x18,0x10,0x1F,0x00,0x00,0x00,0x00},/*"四",26*/ {0x00,0x00,0x00,0x08,0xFC,0x84,0x84,0x84,0x78,0x08,0x68,0x98,0x10,0x00,0x00,0x00}, {0x00,0x00,0x00,0x00,0x07,0x01,0x01,0x01,0x0E,0x02,0x02,0x04,0x07,0x78,0x00,0x00},/*"五",28*/ {0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x60,0xB0,0x20,0x20,0x40,0xFE,0x00,0x00,0x00}, {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3F,0x00,0x00,0x06,0x0C,0x08,0x30,0x00,0x00},/*"六",30*/ {0x00,0x00,0x00,0x00,0x80,0x00,0x7E,0x80,0x00,0x40,0x30,0x18,0x08,0x00,0x00,0x00}, {0x00,0x00,0x00,0x07,0x01,0x01,0x01,0x1F,0x01,0x03,0x02,0x04,0x08,0x30,0x00,0x00},/*"天",32*/ {0x00,0x00,0x00,0xC0,0x00,0x00,0x70,0x80,0x00,0x00,0x80,0x40,0x30,0x1C,0x00,0x00}, {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00},/*":",34*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",35*/ }; /***************************函数声名*********************************/ void ConMove(void); //显示移位子函数 void WriteDS1302(void); //向DS1302写入时间。 void ReadDS1302(void); //读取DS1302中的年,月,日,星期几,小时,分钟和秒. void Fill_timetable(void); //真写timetable数组,起构建显示模板的作用 /*****************************函数***********************************/ void main() { Init595(); //初使化74hc595 Fill_timetable(); //构造显示图形的模板 WriteDS1302(); while(1) { ReadDS1302(); display(); //驱动点阵屏显示matrix数组元素 ConMove(); //控制显示内容向左“位移” } } //写DS1302 void WriteDS1302(void) { WriteByte(Write_Yea,BCD(12)); //写12年 } //读取DS1302中的年,月,日,星期几,小时,分钟和秒. void ReadDS1302(void) { unsigned char temp; temp=ReadByte(Read_Yea); timetable[10]=matrix[temp/16]; timetable[11]=matrix[temp%16]; temp=ReadByte(Read_Mon); timetable[14]=matrix[temp/16]; timetable[15]=matrix[temp%16]; temp=ReadByte(Read_Dat); timetable[18]=matrix[temp/16]; timetable[19]=matrix[temp%16]; temp=ReadByte(Read_Day); timetable[26]=matrix[temp+20]; timetable[27]=matrix[temp+21]; temp=ReadByte(Read_Hou); timetable[28]=matrix[temp/16]; timetable[29]=matrix[temp%16]; temp=ReadByte(Read_Min); timetable[31]=matrix[temp/16]; timetable[32]=matrix[temp%16]; temp=ReadByte(Read_Sec); timetable[34]=matrix[temp/16]; timetable[35]=matrix[temp%16]; } //真写timetable数组,起构建显示模板的作用 void Fill_timetable(void) { unsigned char x; for(x=0;x<8;x++) //填充" " { timetable[x]=matrix[35]; } for(x=0;x<8;x++) //填充" " { timetable[x+36]=matrix[35]; } timetable[8]=matrix[2]; timetable[9]=matrix[0]; timetable[12]=matrix[10]; //补充"年"字 timetable[13]=matrix[11]; timetable[16]=matrix[12]; //补充"月"字 timetable[17]=matrix[13]; timetable[20]=matrix[14]; //补充"日"字 timetable[21]=matrix[15]; timetable[22]=matrix[16]; //补充"星"字 timetable[23]=matrix[17]; timetable[24]=matrix[18]; //补充"期"字 timetable[25]=matrix[19]; timetable[30]=matrix[34]; //补充":"字 timetable[33]=matrix[34]; //补充":"字 } //控制移动子函数 void ConMove(void) { if(++shiftime>1) //更改shiftime可调节字幕移动时间 { shiftime=0; if(++move>7){ move=0; if(++number>words-8) number=0; } } }
/********************************************************************** * File Name: DS1302驱动程序 * Effect: 向DS1302 写/读 时间/数据 * Head: ds1302.h * Explaination: * Author: Mason * 别名: 小菜 * Email Address: 1609099954@qq.com * last modified time:2012-7-25 * Performance: Unfinished * Detail : BurstRead_CLK,BurstRead_RAM,BurstWrite_CLK, * BurstWrite_RAM,这四个函数未调试 **********************************************************************/ #include<reg52.h> #include"ds1302.h" sbit CE =P1^5; //即RST sbit SCLK=P1^6; sbit IO =P1^7; /**************************指令定义*************************************/ #define Write_Sec 0x80 #define Write_Min 0x82 #define Write_Hou 0x84 #define Write_Dat 0x86 #define Write_Mon 0x88 #define Write_day 0x8a #define Write_Yea 0x8c #define Write_WP 0x8e //写保护位 #define Write_TCR 0x90 //涓流充电寄存器写指令 #define Read_Sec 0x81 #define Read_Min 0x83 #define Read_Hou 0x85 #define Read_Dat 0x87 #define Read_Mon 0x89 #define Read_Day 0x8b #define Read_Yea 0x8d #define CLK_BurstW 0xbf //时钟突发模式写 #define CLK_BurstR 0xbf //时钟突发模式读 #define Write_RAM_Begin 0xc0 //RAM第一个字节写指令 #define Read_RAM_Begin 0xc1 //RAM第一个字节读指令 #define RAM_BurstW 0xfe //突发模式写RAM #define RAM_BurstR 0xff //突发模式读RAM /******************************变量定义******************************/ /******************************函数声名******************************/ void SendCmd(unsigned char cmd); //传送地址 void delayus(unsigned char tt); /********************************函数*******************************/ //读取地址RCmd的时间/数据 unsigned char ReadByte(unsigned char RCmd) { unsigned char valu=0x00,temp; CE=0; //初使化 SCLK=0; //初使化,并为rise edge做准备 CE=1; //初使化,传输开始。The SCLK must be low when CE is driven to high level. SendCmd(RCmd); //传送地址 for(temp=0;temp<8;temp++) { valu>>=1; SCLK=0; if(IO==1) valu|=0x80; delayus(1); SCLK=1; delayus(1); } CE=0; //结束传输 return valu; } //向WCmd地址写入时间/数据若写入时间,则时间用#define BCD(time) (time/10*16+time%10)处理. void WriteByte(unsigned char WCmd,unsigned char valu) { unsigned char temp; CE=0; SCLK=0; //初使化,并为rise edge做准备 CE=1; //初使化,传输开始。The SCLK must be low when CE is driven to high level. SendCmd(WCmd); for(temp=0;temp<8;temp++) { SCLK=0; IO=valu&0x01; delayus(1); SCLK=1; delayus(1); valu>>=1; } CE=0; //结束传输 } //突发模式读RAM num个字节 void BurstRead_CLK(unsigned char *ptr) { unsigned char temp,temp2,valu; CE=0; SCLK=0; CE=1; SendCmd(RAM_BurstR); //突发模式读取CLK开始 for(temp2=0;temp2<8;temp2++) { for(temp=0;temp<8;temp++) //读取到的分别是秒,分,时,日,月,星期几,年,写保护位,注意,TCR是不可以突发模式的。 { valu>>=1; SCLK=0; if(IO==1) valu|=0x80; delayus(1); SCLK=1; delayus(1); } *ptr=valu; ptr++; } CE=0; //结束突发模式读 } void BurstRead_RAM(unsigned char *ptr,unsigned char num) { unsigned char temp1,temp2,valu; CE=0; SCLK=0; CE=1; SendCmd(CLK_BurstR); //突发模式读取CLK开始 for(temp2=0;temp2<num;temp2++) { for(temp1=0;temp1<8;temp1++) //读取到的分别是秒,分,时,日,月,星期几,年,写保护位,注意,TCR是不可以突发模式的。 { valu>>=1; SCLK=0; if(IO==1) valu|=0x80; delayus(1); SCLK=1; delayus(1); } *ptr=valu; ptr++; } CE=0; //结束突发模式读 } //突发模式写RAM void BurstWrite_RAM(unsigned char Data[]) { unsigned char size=sizeof(Data),temp1,temp2,valu; if(size>31) size=31; CE=0; SCLK=0; CE=1; SendCmd(RAM_BurstW); for(temp2=0;temp2<size;temp2++) { valu=Data[temp2]; for(temp1=0;temp1<8;temp1++) { SCLK=0; IO=valu&0x01; delayus(1); SCLK=1; delayus(1); valu>>=1; } } CE=0; } void BurstWrite_CLK(unsigned char Time[]) { unsigned char size=sizeof(Time),temp1,temp2,valu; if(size>8) size=8; CE=0; SCLK=0; CE=1; SendCmd(CLK_BurstW); for(temp2=0;temp2<size;temp2++) { valu=Time[temp2]; for(temp1=0;temp1<8;temp1++) { SCLK=0; IO=valu&0x01; delayus(1); SCLK=1; delayus(1); valu>>=1; } } CE=0; } //传送指令 void SendCmd(unsigned char cmd) { unsigned char temp; for(temp=0;temp<8;temp++) { SCLK=0; //为下一个上升沿做准备 IO=cmd&0x01; SCLK=1; delayus(1); cmd>>=1; } } void delayus(unsigned char tt) //tt=1,延时为1.84us { tt--; }
/*************************************************************************************** * File Name: DS1302驱动程序 * Effect: 驱动DS1302 * Head: ds1302.h * Explaination: 给ReadByte,WriteByte一个访问指令(command)(WriteByte函数还需一个向DS1302写入的值), * 程序将读写DS1302 * Author: Mason * 别名: 小菜 * Email Address: 1609099954@qq.com * last modified time:2012-7-25 * Performance: Finished * Detail : BurstRead_CLK,BurstRead_RAM,BurstWrite_CLK, * BurstWrite_RAM,这四个函数未调试 **************************************************************************************/ #ifndef DS1302_H #define DS1302_H extern unsigned char ReadByte(unsigned char RCmd); extern void WriteByte(unsigned char WCmd,unsigned char valu); extern void BurstRead_CLK(unsigned char *ptr); extern void BurstRead_RAM(unsigned char *ptr,unsigned char num); extern void BurstWrite_CLK(unsigned char Time[]); extern void BurstWrite_RAM(unsigned char Data[]); #endif
/*************************************************************************************** * File Name: display头文件 * Effect: 声名外部函数 * Head: display.h * Explaination: * Author: Mason * 别名: 小菜 * Email Address: 1609099954@qq.com * last modified time:2012-7-25 * Performance: Finished * Question: **************************************************************************************/ #ifndef DISPLAY_H #define DISPLAY_H extern void display(void); #endif
涓流充电数据手册里面说得很详细很容易理解。在实际始用中,要看它的时序图呵,另外,需要注意的是CLK(时钟频率)最高只能为2M。不能写得太快。必要时须加延时
子程序。
基本上就这些了,下面附上我的源程序与proteus仿真,程序里面有注释,不过我写程序能力还在提高中,可能写得不好,希望大家有任何想法多和我沟通哈哈,协作学习!
我的邮箱是rwrwrwrw@vip.qq.com
噢,原来不可以加附件,那我传网盘上。
下载地址:http://dl.dbank.com/c0ugq20ab2
2012-08-10
12:29:34