例程:<br /><br />秒 表<br />程序清单<br />//器件为PIC16F877<br /><br />#include <pic.h><br />#include <math.h><br />//此程序实现计时秒表功能,时钟显示范围00.00~99.99秒,分辨度:0.01秒<br />unsigned char s0,s1,s2,s3;<br />//定义0.01 秒、0.1 秒、1秒、10秒计时器<br />unsigned char s[4];<br />unsigned char k ,data ,sreg;<br />unsigned int i;<br />const table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90};<br />//不带小数点的显示段码表<br />const table0[10]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};<br />//带小数点的显示段码表<br />//TMR0初始化子程序<br />void tmint()<br />{<br /> T0CS=0; //TMR0工作于定时器方式<br /> PSA=1; //TMR0不用分频<br /> T0IF=0; //清除TMR0的中断标志<br /> T0IE=1; //TMR0中断允许<br />}<br />//spi显示初始化子程序<br />void SPIINIT()<br />{<br /> PIR1=0;<br /> SSPCON=0x30;<br /> SSPSTAT=0xC0;<br />//设置SPI的控制方式,允许SSP方式,并且时钟下降沿发送。与"74HC595,当其<br />//SCLK从低到高跳变时,串行输入寄存器"的特点相对应<br /> TRISC=0xD7; //SDO引脚为输出,SCK引脚为输出<br /> TRISA5=0; //RA5引脚置为输出,输出显示锁存信号<br />}<br />//系统其它部分初始化子程序<br />void initial()<br />{<br /> TRISB1=0;<br /> TRISB2=0;<br /> TRISB4=1;<br /> TRISB5=1; //设置与键盘有关的各口的输入输出方式<br /> RB1=0;<br /> RB2=0; //建立键盘扫描的初始条件<br />}<br />//SPI传输数据子程序<br />void SPILED(data)<br />{<br /> SSPBUF=data; //启动发送<br /> do {<br /> ;<br /> }while(SSPIF==0);<br /> SSPIF=0;<br />}<br />//显示子程序,显示4位数<br />void dispaly()<br />{<br /> RA5=0; //准备锁存<br /> for(k=4;k>0;k--)<br /> {<br /> data=s[k-1];<br /> if(k==3) data=table0[data];//第二位需要显示小数点<br /> else data=table[data];<br /> SPILED(data); //发送显示段码<br /> }<br /> for(k=0;k<4;k++)<br /> {<br /> data=0xFF;<br /> SPILED(data); //连续发送4个DARK,使显示好看一些<br /> }<br /> RA5=1; //最后给锁存信号,代表显示任务完成<br />}<br />//软件延时子程序<br />void DELAY()<br />{<br /> for(i = 3553; --i ;) continue;<br />} <br />//键扫描子程序<br />void KEYSCAN()<br />{<br />while(1){ <br />while(1)<br /> {<br /> dispaly(); //调用一次显示子程序<br /> if ((RB5==0)||(RB4==0)) break;<br /> }<br /> DELAY(); //若有键按下,则软件延时<br /> if ((RB5==0)||(RB4==0)) break;//若还有键按下,则终止循环扫描,返回<br /> }<br />}<br />//等键松开子程序<br />void keyrelax()<br />{<br />while(1){<br /> dispaly(); //调用一次显示子程序<br /> if ((RB5==1)&&(RB4==1)) break;<br /> } //为防止按键过于灵敏,每次等键松开才返回<br />}<br />//系统赋值初始化子程序<br />void inizhi()<br />{ <br /> s0=0x00;<br /> s[0]=s0;<br /> s1=0x00;<br /> s[1]=s1;<br /> s2=0x00;<br /> s[2]=s2;<br /> s3=0x00;<br /> s[3]=s3; //s0=s1=s2=s3=0,并放入显示缓冲数组中<br /> sreg=0x00; //tmr0中断次数寄存器清0<br />}<br />//中断服务程序<br />void interrupt clkint(void)<br />{<br /> TMR0=0X13; //对TMR0写入一个调整值。因为写入TMR0后接着的<br />//两个周期不能增量,中断需要3个周期的响应时间,<br />//以及C语言自动进行现场保护要消耗周期<br /> T0IF=0; //清除中断标志<br /> CLRWDT();<br /> sreg=sreg+1; //中断计数器加1<br /> if(sreg==40) //中断次数为40后,才对S0,S1,S2,S3 操作<br /> {<br /> sreg=0;<br /> s0=s0+1;<br /> if(s0==10){<br /> s0=0 ;<br /> s1=s1+1;<br /> if(s1==10){<br /> s1=0 ;<br /> s2=s2+1;<br /> if(s2==10){<br /> s2=0;<br /> s3=s3+1;<br /> if(s3==10) s3=0 ;<br /> }<br /> }<br /> }<br /> }<br /> s[0]=s0;<br /> s[1]=s1;<br /> s[2]=s2;<br /> s[3]=s3;<br />}<br />//主程序<br />main()<br />{<br /> OPTION=0XFF;<br /> tmint(); //TMR0初始化<br /> SPIINIT(); //spi显示初始化<br /> initial(); //系统其它部分初始化<br /> di(); //总中断禁止<br />while(1) { <br /> inizhi(); //系统赋值初始化<br /> KEYSCAN(); //键扫描,直到开始键按下<br /> keyrelax(); //等键松开<br /> ei(); //总中断允许<br /> TMR0=0X08;<br />KEYSCAN(); //键扫描直到停止键按下,在键扫描时有显示<br /> keyrelax() ; //等键松开<br /> di(); //总中断禁止<br /> KEYSCAN(); //键扫描到清0键按下,在键扫描时有显示 <br /> keyrelax() ; //等键松开<br /> }<br />}<br />
|