1、第第7章章 数字电子时钟的设数字电子时钟的设计计电子时钟各大模块电子时钟各大模块数码管动数码管动态显示态显示按键控制按键控制时钟时钟串口修改串口修改时钟时钟时钟信号的时钟信号的产生产生一、动态显示模块一、动态显示模块如 果 显 示 缓 存 区 为 36H或 37H将 0BFH传 送 给 P2口正 常 显 示是否如 果 数 组 元 素 序 号 为 6或 7将 0 xBF传 送 给 P2口正 常 显 示是否横杠处理举措横杠处理举措1、汇编语言处理方法、汇编语言处理方法2、C语言处理方法语言处理方法二、键处理模块二、键处理模块 实际中,由于按键的弹片接触的时候,并不是一接触就紧紧的闭合,它还存在一定
2、的抖动,尽管这个时间非常的短暂,但是对于执行时间以微秒为单位的单片机来说它太漫长了。在程序中通过检测连接键盘的I/O口电平,即可以知道按键是否被按下,从而做出相应的响应。常规按键处理程序方式常规按键处理程序方式键 值 获 取(KEY_JUDGE)地 址将 P2值 存 入 中 间 变 量 TEMP中调 用 显 示 子 程 序判 断 此 时 P2的 值 是 否 等 于 TEMP将 TEMP值 高 位 屏 蔽判 断 TEMP的 值 为 多 少键 值 KEY_VALUE为 0键 值 KEY_VALUE为 1键 值 KEY_VALUE为 2键 值 KEY_VALUE为 3键 值 KEY_VALUE为 4
3、调 用 结 束不 等 于TEMP=0X0ETEMP=0X0DTEMP=0X0BTEMP=0X07TEMP=其 他等 于键盘判定执行流程键盘判定执行流程键功能键功能0(修改热键)(修改热键)键 0功 能 子 程 序取 反 闪 烁 标 志 位变 量 SHIFT指 向 秒 显 示 缓 存 区调 用 结 束键功能键功能1(移位选择)(移位选择)键 1功 能 子 程 序判 断 闪 烁 标 志 位 是 否 为 1变 量 SHIFT加 2判 断 SHIFT是 否 超 过 时 显 示 缓 存 区变 量 SHIFT指 向 秒 显 示 缓 存 区调 用 结 束是是否否键功能键功能2(执行加(执行加1)键 2功 能
4、 子 程 序判 断 闪 烁 标 志 位 是 否 为 1执 行 加 1子 程 序调 用 结 束是否键功能键功能3(清零显示单元)(清零显示单元)键 3功 能 子 程 序判 断 闪 烁 标 志 位 是 否 为 1执 行 清 零 子 程 序调 用 结 束是否C51 指针概念指针概念1、指针印象、指针印象指针变量的一般形式为:类型说明符 *变量名;其中“*”表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。例如:uchar*TEMP;TEMP就是一个指针变量,它的值表示了某个无符号字符型数据变量的地址。或者说TEMP指向一无符号字符型数据变量。使用语句:
5、TEMP=0 x30;赋值0 x30给指针型变量TEMP,也就是TEMP指向了地址0 x30,假设地址30H里面存有数据。*TEMP的值指向了地址30H的数值0Xfe。汇编语言中的R0就相当于C语言中的TEMP,而R0和*TEMP表达的是相同的意思。同汇编语言的间接寻址一样,不仅可以取出数值,而且可以存入数据。例如使用指令:*TEMP=0 x78;就上将数值0 x78存放到指针变量TEMP指向的地址2、指针变量的引用及初始化、指针变量的引用及初始化 指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。指针变量的赋值只能赋予地址,决不能赋予任何其它数据。在C语言中,变量的地址是
6、由编译系统分配的,对用户完全透明,用户不知道变量的具体地址,所以上面的例子不能运用于实际程序之中。指针变量有两个操作符:&取地址运算符。取地址运算符。*指针运算符指针运算符C语言中提供了地址运算符&来表示变量的地址,其一般形式为:&变量名;如&a表示变量a的地址,&b表示变量b的地址。uchar a;uchar*p;p=&a;uchar a;uchar*p=&a;上面两段程序是等价的,因为在初始化阶段:uchar*p=&a;等价于等价于 uchar*p;p=&a;但在程序运行过程中,不能采用:*p=&a;因为*p表示的是一个数值,而不能将地址传输给数值。3、指针的初始化、指针的初始化4、指针和
7、数组指针和数组 一个数组是由连续的一块内存单元组成的。一个数组也是由各个数组元素(下标变量)组成的。每个数组元素按其类型不同占有几个连续的内存单元。一个数组元素的首地址也是指它所占有的几个内存单元的首地址,同时C语言规定数组名就是整个数组的地址。例如,在程序中使用了数组uchar data dbuf8;dbuf0的地址就是整个数据的地址。uchar*p;/*定义p为指向字符型型变量的指针*/p=&dbuf0 /*首元素地址赋值*/也可以写为:P=dbuf /*数组名直接赋值*/把dbuf0元素的地址赋给指针变量p。也就是说,p指向数组dbuf的第0号元素。C语言规定:如果指针变量p已指向数组中
8、的一个元素,则p+1指向同一数组中的下一个元素。引入指针变量后,就可以用两种方法来访问数组元素了。如果p的初值为&dbuf 0,则:p+i和dbuf+i同为dbuf i的地址,或者说它们是指向dbuf数组的第i个元素*(p+i)或*(dbuf+i)就是p+i或dbuf+i所指向的数组元素,即dbuf i。例如:*(p+5)或*(dbuf+5)为dbuf 5的值。5、指针作为函数参数、指针作为函数参数 函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型。它的作用是将一个变量的地址传送到另一个函数中。void KEY2_FUNCTION()uchar*TEMP;if(FLASH=1)T
9、EMP=dbuf+SHIFT;ADD1(TEMP);uchar ADD1(uchar*str)uchar TEMP1;TEMP1=(*(str+1)&0X0F)*10+(*(str)&0X0F)+1;*(str+1)=TEMP1/10;*(str)=TEMP1%10;return TEMP1;三、时钟信号的产生三、时钟信号的产生 时钟计时的关键问题是秒的产生,因为秒是最小时钟单元。当选用可编程定时的方式,也就是使用单片机自带的定时器/计数器进行定时。即使使用工作方式1,选用12M晶振,其最大定时时间也只能达到65.536ms。但我们可将定时时间定为50ms,让定时器0计数溢出20次就可得到1s
10、。定时器0也是处于中断的控制方式,设置一个循环计数器,每经历一次中断,它加1。当它的值达到20的时候,表示时间已经过去了1s;此时秒值加1,并清零循环计数器;如果秒值达到60,则分值加1,秒值清零,依次类推。定 时 器 0中 断 服 务 子 程 序循 环 计 数 器 加 1是 否 计 满 20次循 环 计 数 器 清 零秒 值 加 1是 否 为 60s秒 显 示 缓 存 区 清 零分 值 加 1是 否 为 60分分 显 示 缓 存 区 清 零时 值 加 1是 否 为 24时时 显 示 缓 存 区 清 零中 断 返 回是是是是否否否否时钟信号产生流程时钟信号产生流程四、串行修改模块四、串行修改模
11、块 当某一显示单元被选中,也就是处于闪烁状态的时候,我们可以对这个单元的值进行修改。本实例中,增加了串口模块,可通过串口输入来改变显示单元的数值。串 行 中 断 服 务 子 程 序判 断 接 收 标 志 位 是 否 为 1判 断 闪 烁 标 志 位 是 否 为 1串 行 接 收 数 据 拆 分 为 两 个 字 节存 入 相 应 显 示 缓 存 区中 断 返 回否清 零 接 收 标 志 位 RI否是是串行口控制流程串行口控制流程各寄存器的设置各寄存器的设置(1)外中断控制外中断控制外中断0采用的下降沿触发的方式,所以寄存器TCON的IT0位应设置为1 (2)定时器控制方式)定时器控制方式 定时工
12、作方式寄存器TMOD的设置。高4位设置为定时工作方式2(重新加载模式),用于波特率的产生;低4位用于秒计时的产生,设置为定时工作方式1(16位定时/计数模式),用于50ms定时。使用定时器0产生50ms的可编程延时,本章实例晶振选用12MHZ。所以定时器0数据寄存器的初值设定计算方法为:(216-X)1s=50000s,X=3CB0H 定时器1用于波特率发生器,本章实例所使用的晶振为12MHZ,这样产生的波特率会存在误差,但是依然能够保证Proteus仿真。波特率设置为9600 bps,定时器1计数初值设定为:(3)、串口寄存器设置)、串口寄存器设置 在本实例中,设置让串行口工作在方式1,即1个起始位,8个数据位和1个停止位,允许接收,波特率可选,所以寄存器SCON的设置为50H。寄存器PCON的最高位SMOD设置为0,表示波特率不倍增,所以寄存器PCON值设置为00H。(4)、中断寄存器设置)、中断寄存器设置 本实例中使用外中断0、串行中断、定时器0中断、分别将中断控制寄存器IE的EA、ES、ET0、EX0置1。本实例要求定时器0的中断优先级最高,串行中断和外中断0是平级的,所以寄存器IP的设置为02H。