PROCESSOR 16C74
INCLUDE "P16C74B.INC "
SECEQU 0X23
MSEC EQU 0x24
TEMP1 EQU 0X22
FLAG2 EQU 0X28
ORG 0x00
GOTO START
ORG 0x04设定中断向量
BCF STATUS,RP0
BTFSC INTCON,T0IF 判断TIER0中断标志位是否被设置
GOTO TMR0_ISR 若是,则去执行TIMER0中断子程序
RETFIE
START:
CALL PIC_INIT 去设置端口、TIMER0工作滑消模式
BSF INTCON,GIE
BSF INTCON,T0IE
MAIN_LOOP:
程序的主体是个无限循环
BTFSC FLAG2,7
CALL DISPLAY
GOTO MAIN_LOOP
PIC_INIT:
CLRF INTCON
BCF INTCON,T0IE
BSF STATUS,RP0
MOVLW B'00000000'梁掘B’XXXXXXXX’表示单引号中橡让核的数是二
MOVWF TRISB
MOVLW B'00000000'
MOVWF TRISC
BCF STATUS,RP0
MOVLW B'11000000'B’XXXXXXXX’表示单引号中的数是二
MOVWF PORTB
MOVLW B'11000000'
MOVWF PORTC
BSF STATUS,RP0
MOVLW B'11000100'
MOVWF OPTION_REG 对TIMER0工作模式进行设置,32分频
BCF STATUS,RP0
MOVLW 0X06
MOVWF TMR0
CLRF SEC
CLRF MSEC
CLRF TEMP1
CLRF FLAG2
RETURN
TMR0_ISR:
CLRWDT
BSF FLAG2,7
BCF INTCON,T0IF
MOVLW 0X06
MOVWF TMR0
CLRWDT
INCF TEMP1,1
MOVF TEMP1,0
SUBLW .125 125-TEMP
BTFSS STATUS,2
RETFIE
CLRWDT
CLRF TEMP1
INCF MSEC,1
RETFIE
DISPLAY:
MOVF MSEC,0
SUBLW .10
BTFSS STATUS,2
GOTO NEXT_1
CLRWDT
CLRF MSEC
INCF SEC,1
MOVF SEC,0
SUBLW .6
BTFSS STATUS,2
GOTO NEXT_1
CLRF SEC
NEXT_1:
CLRWDT
MOVF MSEC,W
CALL CHAR_CODE
MOVWF PORTC
MOVF SEC,W
CALL CHAR_CODE
MOVWF PORTB
BCF FLAG2,7
RETURN
CHAR_CODE:
ADDWF PCL,1PCL+=W
RETLW B'11000000' Code for 0
RETLW B'11111001' Code for 1
RETLW B'10100100' Code for 2
RETLW B'10110000' Code for 3
RETLW B'10011001' Code for 4
RETLW B'10010010' Code for 5
RETLW B'10000010' Code for 6
RETLW B'11111000' Code for 7
RETLW B'10000000' Code for 8
RETLW B'10010000' Code for 9
END
共阳共阴只是你在选COM端时给其高低电平的问题无关大雅我给一段PIC单片机的程序让你参考一下,如果你看懂的话应该能做出来了
#include <pic.h>
#include <math.h>
//此程序实现计时秒表功能,时钟显示范围00.00~99.99秒,分辨度:0.01秒
unsigned char s0,s1,s2,s3;
//定义0.01 秒、0.1 秒、1秒、冲空物10秒计时器
unsigned char s[4];
unsigned char k ,data ,sreg;
unsigned int i;
const table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90};
//不带小数点的显示段码表
const table0[10]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};
//带小数点的显示段码表
//TMR0初始化子程序
void tmint()
{
T0CS=0;//TMR0工散液作于定时器方式
PSA=1; //TMR0不用分频
T0IF=0; //清除TMR0的中断标志
T0IE=1; //TMR0中断允许
}
//spi显示初始化子程序
void SPIINIT()
{
PIR1=0;
SSPCON=0x30;
SSPSTAT=0xC0;
//设置SPI的控制方式,允许SSP方式,并且时钟下降沿发送。与"74HC595,当其
//SCLK从低到高跳变时,串行输入寄存器"的特点相对应
TRISC=0xD7; //SDO引脚为输出,SCK引脚为输出
TRISA5=0;//RA5引脚置为输出,输出显示锁存信号
}
//系统其它部分初始化子程序
void initial()
{
TRISB1=0;
TRISB2=0;
TRISB4=1;
TRISB5=1;//设置与键盘有关的各口的输入输出方式
RB1=0;
RB2=0; //建立键盘扫描的初始条件
}
//SPI传输亏升数据子程序
void SPILED(data)
{
SSPBUF=data; //启动发送
do {
;
}while(SSPIF==0);
SSPIF=0;
}
//显示子程序,显示4位数
void dispaly()
{
RA5=0; //准备锁存
for(k=4;k>0;k--)
{
data=s[k-1];
if(k==3) data=table0[data];//第二位需要显示小数点
else data=table[data];
SPILED(data); //发送显示段码
}
for(k=0;k<4;k++)
{
data=0xFF;
SPILED(data); //连续发送4个DARK,使显示好看一些
}
RA5=1; //最后给锁存信号,代表显示任务完成
}
//软件延时子程序
void DELAY()
{
for(i = 3553; --i ;) continue;
}
//键扫描子程序
void KEYSCAN()
{
while(1){
while(1)
{
dispaly(); //调用一次显示子程序
if ((RB5==0)||(RB4==0)) break;
}
DELAY(); //若有键按下,则软件延时
if ((RB5==0)||(RB4==0)) break;//若还有键按下,则终止循环扫描,返回
}
}
//等键松开子程序
void keyrelax()
{
while(1){
dispaly();//调用一次显示子程序
if ((RB5==1)&&(RB4==1)) break;
} //为防止按键过于灵敏,每次等键松开才返回
}
//系统赋值初始化子程序
void inizhi()
{
s0=0x00;
s[0]=s0;
s1=0x00;
s[1]=s1;
s2=0x00;
s[2]=s2;
s3=0x00;
s[3]=s3; //s0=s1=s2=s3=0,并放入显示缓冲数组中
sreg=0x00;//tmr0中断次数寄存器清0
}
//中断服务程序
void interrupt clkint(void)
{
TMR0=0X13; //对TMR0写入一个调整值。因为写入TMR0后接着的
//两个周期不能增量,中断需要3个周期的响应时间,
//以及C语言自动进行现场保护要消耗周期
T0IF=0; //清除中断标志
CLRWDT();
sreg=sreg+1;//中断计数器加1
if(sreg==40)//中断次数为40后,才对S0,S1,S2,S3 *** 作
{
sreg=0;
s0=s0+1;
if(s0==10){
s0=0 ;
s1=s1+1;
if(s1==10){
s1=0 ;
s2=s2+1;
if(s2==10){
s2=0;
s3=s3+1;
if(s3==10) s3=0 ;
}
}
}
}
s[0]=s0;
s[1]=s1;
s[2]=s2;
s[3]=s3;
}
//主程序
main()
{
OPTION=0XFF;
tmint(); //TMR0初始化
SPIINIT();//spi显示初始化
initial(); //系统其它部分初始化
di(); //总中断禁止
while(1) {
inizhi();//系统赋值初始化
KEYSCAN(); //键扫描,直到开始键按下
keyrelax(); //等键松开
ei();//总中断允许
TMR0=0X08;
KEYSCAN(); //键扫描直到停止键按下,在键扫描时有显示
keyrelax() ; //等键松开
di();//总中断禁止
KEYSCAN(); //键扫描到清0键按下,在键扫描时有显示
keyrelax() ; //等键松开
}
}
本电子钟采用PIC16C55单片机控制,适于温室的定时恒温或自来水的定时定压控制等。PIC16C55单片机工作电压为2.5~6.25V,功耗低、驱动能力强。本电子钟可以控制一路负载在24小时内的3次开/关一个双限触发的定时输出口,既可接传统的功率保持型继电器,也可接脉冲继电器。本机用四位LED数码管扫描式显示,还有消隐(省电)工作方式,使用起来非常灵活、方便。一、 电子钟工作原理
电子钟电路见图1。RB7口是定时指示端,在定时开期间输出高电平,驱动V1发光,该口也可经缓冲作定时输出口RB6是双限触发控制的定时输出口,其工作方式是:在RB7高电平期间,若RB1为高电平,则RB6输出高电平若RB0为高电平,RB6输出低电平若RB1、RB0同为低电平,RB6保持原态同为高电平时,RB6输出低电平。RB5、RB4用于驱动脉冲继电器,RB6上升沿触发RB5输出高电平开脉冲在RB6下降沿触发RB4时,RB4端输出高电平关脉冲,开/关脉冲的持续时间均为125ms。
图 1
RB3是消隐控制器,接高电平(即SK1闭合)时,显示屏及秒闪正常否则,显示消隐。显示消隐时,时钟及各控制逻辑都正常运行,如忽略RB4至RB7各口的驱动电流,则在3V供电时,整机电流不足20μA,即两节5号电池可用数月!RB2选择数码管极性,RB2为低电平,使用共阴LEDRB2为高电平,则用共阳LED。数码管的极性是在上电初始化时,根据 RB2口状态确定的,工作过程中改变RB2的电平则不起作用。
本机设S1~S4四个按键,S1是功能选择键,S2是小时增量调整,S3是分伍滑卜钟增量,S4用于分钟减量调节,其使用方法为:
上电时,RB5至RB7均为低电平,RB4端送出一个关脉冲,使SK1闭合,整机正常显示、让则工作,RC7口送出秒闪脉冲,RC6~RC0送字段码。RA3~RA0分别为10时、时、10分、分位的位码输出。这时,按一下S2或S3(时增量/ 分增量键),可使RB7端置位或复位。
在正常走时期间,秒闪正常在校对或设置定时时,秒停闪。例如:在正常走时期间,按一下S1键,秒闪停止,屏幕显示J-,表示可以校对时间。这时再按S2~S4中任一键,屏幕显示现在时间,但秒不闪,此刻可按S2~S4校对时钟。再次按S1,屏幕显示 1∪,表示可以设定第一次开时间,此时按S2~S4对时间进行查看及设置。继续按S1,系统显示1∩,表示可设置第一次关时间……依次进行。设置好系统及 3次开关时间后,整机回到正常显示状态,秒闪恢复。
如欲取消某次开/关定时,只需把该次的开与关时间设置成相同值即可。
笔者曾把该时钟用于定时定压供水控制系统,RB6端用于驱动继电器(也可用RB5与RB4两端驱动脉冲继电器),RB1端接水压(水位)的低限输入,RB0 端接高限输入,设置好定时,一个简易的定时定压自动供水系统即告完成。
二、 编程技巧
PIC16C55单片机程序存储器只有512字节,加上采用外接32768Hz晶体振荡方式,时钟速度较低,因此,统筹好系统的工作时序与人机界面之间的关系是软件设计成败的关键。本机编程采用如下方案:软件工作流程见附图2。
图 2
PIC16C55单片机的一个机器周期是4个时钟周期,不难算出,本系统中每秒有8192个机器周期。在编制软件时,先设定单片机内部定时计数器F1的计数方式为机器周期的64分频。这样,每当F1溢出时,系统递加2秒。平时,系统每128个机器周期内用RC口与RA口驱动扫描一次显示屏,可保证每秒内扫描64次显示屏,基本上无闪烁感。而 128个机器周期腔穗正是F1的第0位(为便于叙述以下简记为F1?0)每次下降沿的间隔时间,我们可以编一段程序,当F1?0的下降沿到来时,扫描一次显示屏,每当F1的低4位为全0时(125ms一次)使系统检测一次RB口与按键状态,并进行相关处理,部分相关程序如下:
WAIT BTFSC 1,0 等待F1?0的下降沿,编程时
GOTO WAIT 要保证每次下降沿前到此
MOVFW 1
SKPNZ
GOTO CLOCK F1=0,满2秒,转时钟处理
ANDLW 0FH 屏蔽F1高4位
SKPZ
GOTO DISPLAYF1低4位不为0,转显示
MOVLW 0C0H 满125mS,使RB口脉冲复位
ANDWF 6,1
MOVLW 0FH 检测按键
TRIS 7
MOVFW 7
ANDLW 0FH 保留按键数据
SKPZ
GOTO AN有键值,转按键处理
DISPLAY …… 显示扫描,定时管理RB口
CLOCK …… 时钟,定时处理程序
AN …… 按键管理程序
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)