单片机计时秒表程序方案设计书.docx
《单片机计时秒表程序方案设计书.docx》由会员分享,可在线阅读,更多相关《单片机计时秒表程序方案设计书.docx(12页珍藏版)》请在冰豆网上搜索。
单片机计时秒表程序方案设计书
pic单片机计时秒表程序设计(时钟显示范围00.00~99.99秒,分辨度为0.01秒)
作者:
来源:
本站原创 点击数:
1676 更新时间:
2008年07月12日
//此程序实现计时秒表功能,时钟显示范围00.00~99.99秒,分辨度:
0.01秒
#include"p18f458.h"
unsignedchars[4]。
//定义0.01秒、0.1秒、1秒、10秒计时器
unsignedchark,data,sreg。
unsignedinti。
consttable[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90}。
//不带小数点的显示段码表
consttable0[10]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10}。
//带小数点的显示段码表
voidclkint(void)。
//TMR0初始化子程序
voidtmint()
{
T0CON=0XCF。
//设定TMR0L工作于8位定时器方式
//内部时钟,TMR0不用分频
INTCON=0X20。
//总中断禁止,TMR0中断允许,清除TMR0的中断标志
INTCON2bits.TMR0IP=1。
//TMR0中断高优先级
RCONbits.IPEN=1。
//使能中断优先级
}
//系统其它部分初始化子程序
voidinitial()
{
TRISA=0x00。
//A口设置为输出
TRISB=0XF0。
//RB1输出,RB4输入
TRISC=0x00。
//SDO引脚为输出,SCK引脚为输出
TRISE=0x00。
//E口设置为输出
SSPCON1=0x30。
//SSPEN=1。
CKP=1,FOSC/4
SSPSTAT=0xC0。
//时钟下降沿发送数据
PIR1=0。
//清除SSPIF标志
data=0X00。
//待显示的寄存器赋初值
PORTBbits.RB1=0。
PORTAbits.RA3=0。
PORTE=0。
//将K1,K2,K3,K4四条列线置0
}
//SPI传输数据子程序
voidSPILED(chardata)
{
SSPBUF=data。
//启动发送
do
{
。
}while(PIR1bits.SSPIF==0)。
PIR1bits.SSPIF=0。
}
//显示子程序,显示4位数
voiddispaly()
{
PORTAbits.RA5=0。
//准备锁存
for(k=0。
k<4。
k++)
{
data=s[k]。
if(k==2)data=table0[data]。
//个位需要显示小数点
elsedata=table[data]。
SPILED(data)。
//发送显示段码
}
for(k=0。
k<4。
k++)
{
data=0xFF。
SPILED(data)。
//连续发送4个DARK,使显示好看一些
}
PORTAbits.RA5=1。
//最后给锁存信号,代表显示任务完成
}
//软件延时子程序
voidDELAY()
{
for(i=3553。
--i。
)
continue。
}
//键扫描子程序
voidKEYSCAN()
{
while
(1)
{
dispaly()。
//调用一次显示子程序
while(PORTBbits.RB4==0)
{
DELAY()。
//若有键按下,则软件延时
break。
}
if(PORTBbits.RB4==0)break。
//若还有键按下,则终止循环扫描,返回
}
}
//等键松开子程序
voidkeyrelax()
{
while
(1)
{
dispaly()。
//调用一次显示子程序
if(PORTBbits.RB4==1)break。
//为防止按键过于灵敏,每次等键松开才返回
}
}
/*高优先级中断向量*/
#pragmacodeInterruptVectorHigh=0x08
voidInterruptVectorHigh(void)
{
_asm
gotoclkint//跳到中断程序
_endasm
}
//中断服务程序
#pragmacode
#pragmainterruptclkint
voidclkint()
{
TMR0=0X13。
//对TMR0写入一个调整值。
因为写入TMR0后接着的
//两个周期不能增量,中断需要3个周期的响应时间,
//以及C语言自动进行现场保护要消耗周期
INTCONbits.T0IF=0。
//清除中断标志
sreg=sreg+1。
//中断计数器加1
if(sreg==40)//中断次数为40后,才对S0,S1,S2,S3操作
{
sreg=0。
s[0]=s[0]+1。
if(s[0]==10)
{
s[0]=0。
s[1]=s[1]+1。
if(s[1]==10)
{
s[1]=0。
s[2]=s[2]+1。
if(s[2]==10)
{
s[2]=0。
s[3]=s[3]+1。
if(s[3]==10)s[3]=0。
}
}
}
}
}
//主程序
//提供此单片机程序有问题请联系
main()
{
tmint()。
//TMR0初始化
initial()。
//spi显示初始化及系统其它部分初始化
INTCONbits.GIE=0。
//总中断禁止
while
(1)
{
for(k=0。
k<4。
k++)
{
s[k]=0。
}
sreg=0。
//赋显示初值
dispaly()。
//调用一次显示子程序
KEYSCAN()。
//键扫描,直到开始键按下
keyrelax()。
//等键松开
INTCONbits.GIE=1。
//总中断允许
KEYSCAN()。
//键扫描直到停止键按下,在键扫描时有显示
keyrelax()。
//等键松开
INTCONbits.GIE=0。
//总中断禁止
KEYSCAN()。
//键扫描到清0键按下,在键扫描时有显示
keyrelax()。
//等键松开
}
}
---------------------汇编语言版本的pic单片机计时秒表程序设计--------------------------------------。
此程序实现计时秒表功能
。
时钟显示范围:
00.00秒-99.99秒,分辨度:
0.01秒
。
通过按键来启动计时、停止计时及清0
。
即第一次按下任意键开始计时,第二次按下任意键停止计时。
第三次按下任意键使LED清0,等待下一次计时开始
LISTP=18F458
INCLUDE"P18F458.INC"
S0EQU0X20。
0.01秒计时器
S1EQUS0+1。
0.1秒计时器
S2EQUS0+2。
1秒计时器
S3EQUS0+3。
10秒计时器
SREGEQUS0+4。
软计数器
LEDFEQUS0+5。
显示的LED的位置指示寄存器
XW_TEMPEQUS0+6。
用于中断中保护W的值
XHOSTSEQUS0+7。
用于中断中保护STATUS的值
DEYHEQUS0+8
DEYLEQUS0+9。
以上两个寄存器用于软件延时
HOSTFEQUS0+0A。
用于中断中保护FSR0L的值
TEMPEQUS0+0B。
用于存放临时值
ORG0X00
GOTOMAIN
ORG0X08
GOTOCLKINT。
转向中断服务程序
ORG0X30
。
数字到段码的转换子程序(最好放在程序开头,避免超过2K的空间发生跨页读表)
。
************不带小数点的共阳极码表**************
CONVERTADDWFPCL,1
RETLW0XC0。
0,显示段码与具体的硬件连接有关
RETLW0XF9。
1
RETLW0XA4。
2
RETLW0XB0。
3
RETLW0X99。
4
RETLW0X92。
5
RETLW0X82。
6
RETLW0XD8。
7
RETLW0X80。
8
RETLW0X90。
9
RETLW0X88。
A
RETLW0X83。
B
RETLW0XC6。
C
RETLW0XA1。
D
RETLW0X86。
E
RETLW0X8E。
F
RETLW0X7F。
"."
RETLW0XBF。
"-"
RETLW0X89。
H
RETLW0XFF。
DARK
RETURN
。
*********带小数点的共阳极码表***********
CONVERT2ADDWFPCL,1
RETLW0X40。
0
RETLW0X79。
1
RETLW0X24。
2
RETLW0X30。
3
RETLW0X19。
4
RETLW0X12。
5
RETLW0X02。
6
RETLW0X78。
7
RETLW0X00。
8
RETLW0X10。
9
RETURN
。
***********SPI发送显示子模块************
TRANSMIT
CLRFPORTA。
LACK送低电平,为锁存做准备
MOVWFSSPBUF。
启动发送
WAITNOP
BTFSSPIR1,SSPIF
GOTOWAIT。
等待发送结束
BCFPIR1,SSPIF。
清除中断标志
RETURN
。
***********显示子程序模块************
DISPLAY
MOVLW0X01
MOVWFLEDF
MOVLW0XA0
MOVWFFSR0L
AGAINXIAN
MOVFLEDF,W
SUBLW0X03
BTFSSSTATUS,Z
GOTOXIANB
MOVFINDF0,W
CALLCONVERT2。
若是个位,则查带小数点的码表
GOTOTRAN
XIANBMOVFINDF0,W
CALLCONVERT
TRANCALLTRANSMIT。
发送一个显示数据
INCFFSR0L
INCFLEDF
MOVFLEDF,W
SUBLW0X05
BTFSSSTATUS,Z
GOTOAGAINXIAN
MOVLW0X01
MOVWFLEDF
XIANDARK
MOVLW0X27
CALLCONVERT
CALLTRANSMIT
INCFLEDF
MOVFLEDF,W
SUBLW0X05
BTFSSSTATUS,Z
GOTOXIANDARK。
显示4个"DARK"
BSFPORTA,5。
最后给一个锁存信号,代表一次显示任务完成
RETURN
。
**********S0计数溢出处理子程序***************
CS0
CLRFS0
INCFS1
RETURN
。
**********S1计数溢出处理子程序***************
CS1
CLRFS1
INCFS2
RETURN
。
**********S2计数溢出处理子程序***************
CS2
CLRFS2
INCFS3
RETURN
。
**********S3计数溢出处理子程序***************
CS3
CLRFS3
RETURN
。
***********时钟中断服务程序*******************
CLKINT
MOVWFXW_TEMP。
保存W的值
SWAPFSTATUS,W
MOVWFXHOSTS。
暂存STATUS的值
MOVFFSR0L,W
MOVWFHOSTF。
保存FSR0L的值。
以上程序为中断现场保护
MOVLW0X13
MOVWFTMR0L。
对TMR0L写入一个调整值,因为写入
。
TMR0L后接着的两个周期不能增量
BCFINTCON,T0IF。
清除中断标志
INCFSREG
MOVFSREG,W
SUBLW0X28。
TMR0L每250us中断一次
BTFSSSTATUS,Z。
其中断40次后才执行对S0S1S2S3的操作
GOTOTIFAN
CLRFSREG
INCFS0
MOVFS0,W
SUBLW0X0A
BTFSCSTATUS,Z
CALLCS0
MOVFS1,W
SUBLW0X0A
BTFSCSTATUS,Z
CALLCS1
MOVFS2,W
SUBLW0X0A
BTFSCSTATUS,Z
CALLCS2
MOVFS3,W
SUBLW0X0A
BTFSCSTATUS,Z
CALLCS3
TIFAN
MOVFHOSTF,W。
以下为中断现场恢复
MOVWFFSR0L。
恢复间接寻址指针FSR0L的值
SWAPFXHOSTS,W
MOVWFSTATUS。
恢复STATUS的值
SWAPFXW_TEMP,1
SWAPFXW_TEMP,W。
恢复W的值
RETFIE
。
***********TMR0初始化子程序***************
CLKINSUB
MOVLW0XCF
MOVWFT0CON。
设定TMR0L工作于8位定时器方式
。
内部时钟,TMR0不用分频
BCFINTCON,TMR0IF。
清除TMR0的中断标志
BCFINTCON,GIE。
总中断禁止
BSFINTCON,TMR0IE。
TMR0中断允许
BSFINTCON2,2。
TMR0中断高优先级
BSFRCON,7。
使能中断优先级
RETURN
。
***************系统初始化子程序*****************
MAINSUB
BCFTRISA,5。
置RA5为输出方式,以输出锁存信号
BCFTRISB,1
BCFTRISA,3
BCFTRISE,0
BCFTRISE,1
BSFTRISB,4。
设置与键盘有关的各口的输入输出方式
BCFTRISC,5
BCFTRISC,3。
设置SCK与SDO为输出方式
BCFINTCON,GIE。
关闭所有中断
MOVLW0XC0
MOVWFSSPSTAT。
设置SSPSTAT寄存器
MOVLW0X30
MOVWFSSPCON1。
设置SPI的控制方式,允许SSP方式,
。
并且时钟下降沿发送,与"74HC595当
。
其SCLK从低到高平跳变时,串行输入数据
。
(DI)移入寄存器"的特点相对应
RETURN。
返回
。
***********键扫描子程序********************
KEYSCAN
BCFPORTB,1
BCFPORTA,3
BCFPORTE,0
BCFPORTE,1。
送低电平至K1,K2,K3,K4
RETURN
。
*********键盘去抖子程序(8ms的延时)******************
KEYDELAY
MOVLW0X0A
MOVWFDEYH
AGAIN2MOVLW0XFF
MOVWFDEYL
AGAIN1DECFSZDEYL,1
GOTOAGAIN1
DECFSZDEYH,1
GOTOAGAIN2。
具体程序语句参考3.2节
RETURN
。
*************显示缓冲区处理子程序****************
XIANHUAN
MOVLW0XA0
MOVWFFSR0L
RLNCFS0,0
MOVWFTEMP
INCFTEMP,0
MOVWFINDF0
INCFFSR0L
RLNCFS1,0
MOVWFTEMP
INCFTEMP,0
MOVWFINDF0
INCFFSR0L
RLNCFS2,0
MOVWFTEMP
INCFTEMP,0
MOVWFINDF0
INCFFSR0L
RLNCFS3,0
MOVWFTEMP
INCFTEMP,0
MOVWFINDF0
RETURN
。
**************主程序******************
MAINNOP
CALLMAINSUB。
系统初始化
CALLCLKINSUB。
调用时钟初始化子程序
DENJIANBCFINTCON,GIE
CLRFS0
CLRFS1
CLRFS2
CLRFS3
CLRFSREG
CLRFLEDF。
S0=S1=S2=S3=0
CALLXIANHUAN。
把S3、S2、S1、S0的值装入显示缓冲区
CALLDISPLAY。
显示
DENANBCFINTCON,GIE。
关中断
CALLKEYSCAN。
进行键扫描
BTFSSPORTB,4
GOTOXIAODOU1。
如起始键按下,则消抖动
GOTODENAN。
如起始键没按下,则继续等待
XIAODOU1
CALLKEYDELAY。
延时消抖动
CALLKEYSCAN。
再次进行键扫描
BTFSCPORTB,4
GOTODENAN。
若为干扰,则再次等待键按下
CLRFS0
CLRFS1
CLRFS2
CLRFS3
CLRFSREG。
设置新一次计时的初始条件
WAITSCALLKEYSCAN
BTFSSPORTB,4
GOTOWAITS。
为了防止按键过于灵敏,等键松开后再进行
。
下面的操作
BSFINTCON,GIE。
开总中断
HERECALLXIANHUAN。
显示缓冲区处理
CALLDISPLAY。
即时更新显示内容
CALLKEYSCAN
BTFSSPORTB,4
GOTOXIAODOU。
若停止计时键按下,则消抖
GOTOHERE。
若停止计时键没按下,则继续等待中断计时
XIAODOU
CALLDISPLAY。
利用消抖动时间调用显示程序
CALLDISPLAY
CALLDISPLAY
CALLDISPLAY
CALLDISPLAY
CALLDISPLAY
CALLDISPLAY
CALLDISPLAY
CALLDISPLAY
CALLKEYSCAN
BTFSCPORTB,4
GOTOHERE。
若为干扰,则继续等待停止键按下
BCFINTCON,GIE。
若停止键按下,则禁止中断
CALLDISPLAY。
若不为干扰,则禁止中断,更新显示内容
WAITRCALLKEYSCAN
BTFSSPORTB,4
GOTOWAITR。
为了防止按键过于灵敏,等键松开后再进行
。
下面的操作
DENDAICALLKEYSCAN
BTFSCPORTB,4
GOTODENDAI。
循环进行键扫描,等待清0键按下
CALLKEYDELAY。
延时消抖
CALLKEYSCAN
BTFSCPORTB,4
GOTODENDAI
WAIT19CALLKEYSCAN
BTFSSPORTB,4
GOTOWAIT19。
等键松开
GOTODENJIAN。
新一次计时开始
END