PIC16F877A TIMER1计数操作

合集下载

PIC16F877A简单计算器设计报告 汇编语言 四位无符号整数加减乘除

PIC16F877A简单计算器设计报告 汇编语言 四位无符号整数加减乘除

课程设计报告课程名称:单片机原理与接口技术课程设计设计题目:简单计算器院系:机电工程学院班级:2010级电气工程及其自动化专业姓名:学号:指导教师:史丽萍,闫广明,张波,张扬,王冠然设计时间:2013年12月一、设计方案描述与论证我们所设计的是一个简单计算器,它具有四位数以内的整数加减乘除运算。

可以在输入错误的时候退格,也可以初始化。

在初始化的状态下可以进行关机以减少耗能。

显示使用的数码管扫描显示的方法来显示数字,所以我们每一次运算前我们都需要将个位、十位、百位和千位相结合。

我们使用的是4×4的键盘,检测的时候是进行键盘扫描来完成确定哪一个键被摁下,然后是否释放。

键盘被摁下后,先判断是什么键。

如果是数字键,则进行数的输入,首先先把百位的数值赋给千位,十位赋给百位,个位赋给十位,然后把摁下键的对应数赋给个位。

如果是算法键,则将对应的算法寄存地址赋上相应算法的值,并且在下一次输入数字时把十位、百位和千位清零以完成下一次的赋值,而这一次的值将转换为一个数储存在相应的地址中。

当按下的是退格键,则将十位赋值给个位,百位赋值给十位,千位赋值给百位然后千位清零。

当按下的是等号键的时候,将前一次储存的数取出与这一次的数进行相应的运算然后将得到的二进制数拆分为个位、十位、百位和千位然后扫描显示就可以。

复位键是使用的中断,当个位、十位、百位和千位都不为零的时候按下将会初始化计算器的所有数据,如果个位、十位、百位和千位均为零这进入休眠状态等待下一次中断的唤醒。

二、硬件设计部分我们使用的是PIC16F877A单片机,使用四位的八段数码管,4×4的键盘和一个独立的中断键。

八段数码管我们使用的是共基极的接法,所以当给出低电平的时候导通,给出高电平的时候关断。

我们以RD端口来控制段选,分别以RB0控制a、RB1控制b、RB2控制c、RB3控制d、RB4控制e、RB5控制f、RB6控制g和RB7控制dp。

以RD1、RD2、RD3和RD4端口分别控制位选的千位、百位、十位和个位。

PIC16F877A功能及其编程

PIC16F877A功能及其编程
RA3=1; NOP(); RA4=0;
4.1.1 端口A
因此,在使用RA口时,除了要设置TRISA外,有 时相关寄存器也要设置。
注意:在上电复位时,与AN有关的端口的默认 设置是作为模拟端口,即ADCON1(见4.6)中默认 值为0b00xx0000,这个值的设置结果是除RA4外的所 有的RA引脚都作为模拟输入。
信的时钟线; RC7/RX/DT:IO引脚、异步串行通信的接收、同步串行通
信的数据线。
4.1.4 端口D
端口D有8个引脚,它除了作为普通IO口外, 还能作为并行从动口使用。
4.1.5 端口E 端口E只有3个引脚,它们都可以作为AD转换
的模拟电压输入口,功能如下:
RE0/RD/AN5:IO引脚、并行从动口的读控制、 模拟电压输入通道AN5;
➢ 中断的特点:可返回性。中断处理结束后必须能 回到原先的程序,并且能继续运行原先的程序,
这就需要在中断时能进行现场保护与恢复。
中断的执行过程
➢ 中断发生:程序执行到某行,突然事件(能够产 生中断的事件)发生,产生中断。
➢ 断点保护:CPU自动将中断时刻即将要执行的下 一条指令的地址压入堆栈。
➢ 中断响应:CPU自动将PC强制设为0X0004,且GIE =0。执行中断服务程序(自动完成现场保护与恢 复,手动清中断标志位)。
将被调试系统占用,因此在调试时此二个引脚暂 不能使用。
3、8个引脚具有内部弱上拉使能控制 由OPTION_REG寄存器的第7位RBPU控制,如果弱 上拉使能,作为输入的RB口在端口悬空时将被上拉 到高电平。以RB0为例,如下图所示:
4、RB0/INT具有外部中断功能。
5、RB的的高4位还具有电平变化中断功能
ADIE

基于PIC16F877A单片机的温度,时间显示

基于PIC16F877A单片机的温度,时间显示

基于PIC16F877A单片机的温度,时间显示以及闹钟设置,硬件和软件配备一,硬件图#include<pic.h>__CONFIG(0x3B31);#define rs RD0#define rw RD1#define en RD2#define BEEP RD3 #define s1 RA0#define s2 RA1#define s3 RA2#define s4 RA3#define uint unsigned int#define uchar unsigned charsigned char set_time[7]={0,58,23,6,1,5,12};//秒分时星期日月年signed char read_time[7]={0,0,0,0,0,0,0};signed char shi=7,fen=15,alarm_time=1,reapeat_fen=2,cent;//闹钟时,闹钟分,闹铃响分钟,闹铃响间隔uchar s1_num,s2_num;const uchar alarm[]={"ALARM TIME:"};const uchar mode[]={"MODE:"};const uchar rpt[]={"RPT:"};const uchar min[]={"min"};void PORT_INIT(){TRISA=0xff;//A口设置为输入ADCON1=0x06;//RA口上电复位为模拟输入口TRISC3=1;//SCL和SDA设置为输入TRISC4=1;TRISD=0x00;//D口设置为输出}void IIC_INIT(){SSPCON=0x28;STAT_SMP=0;SSPADD=4;}void delayms(uint z)//延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void delayus(uint k){while(k--);}void write_byte_low(uchar R1,uchar flag0)//写一个字节的低4位,flag0为指令/数据选择位{ //,0为写指令,1为写数据uchar low;rs=flag0;low=R1&0x0f;low=low<<4;PORTD&=0x0f;NOP();PORTD|=low;NOP();//写指令的低4位en=1;delayus(20);en=0;}void lcd_write(uchar dat,uchar flag1)//写指令/数据到1602{uchar dat_high,dat_low;dat_high=dat>>4;write_byte_low(dat_high,flag1);dat_low=dat&0x0f;write_byte_low(dat_low,flag1);NOP();}void write_string(uchar address,uchar const *str)//往指定的地址写字符串{uchar i=0;lcd_write(address,0);while(str[i]!='\0'){lcd_write(str[i],1);delayus(5);i++;}}void LCD_INIT()//初始化函数{rw=0;en=0;delayms(20);write_byte_low(0b0011,0);delayms(1);write_byte_low(0b0011,0);delayus(10);write_byte_low(0b0011,0);delayus(10);write_byte_low(0b0010,0);delayms(1);lcd_write(0x28,0);delayms(5);lcd_write(0x0c,0);delayms(5);lcd_write(0x01,0);delayms(5);lcd_write(0x06,0);delayms(5);}void naoling(){uchar i;for(i=0;i<20;i++){BEEP=1;delayus(5);BEEP=0;delayus(5);}}void IIC_SEND(uchar num){SSPBUF=num;while(STAT_RW==1);//等待发送结束while(SSPIF==0);while(ACKSTAT==1);//等待应答}signed char read_temp()//读温度{signed char temp;SEN=1;while(SEN==1);IIC_SEND(0b10011010);IIC_SEND(0);RSEN=1;while(RSEN==1);IIC_SEND(0b10011011);RCEN=1;while(RCEN==1);// SSPIF=0;// while(SSPIF==0);//等待接收结束temp=SSPBUF;PEN=1;while(PEN==1);return temp;}void dispose()//BCD数据处理{uchar i,temp1,temp2;for(i=0;i<7;i++){temp1=set_time[i]/10;temp2=set_time[i]%10;set_time[i]=temp1*16+temp2;}}void time_csh()//时间初始化{uchar i;dispose();for(i=0;i<7;i++){SEN=1;//起始信号while(SEN==1);//检测起始信号是否已完成IIC_SEND(0xd0);IIC_SEND(i);IIC_SEND(set_time[i]);PEN=1;//停止信号while(PEN==1);}}void read_ds1307()//读时间{uchar k;for(k=0;k<8;k++){SEN=1;//起始信号while(SEN==1);IIC_SEND(0xd0);IIC_SEND(k);PEN=1;//停止信号while(PEN==1);RSEN=1;//重新启动while(RSEN==1);IIC_SEND(0xd1);SSPIF=0;RCEN=1;while(SSPIF==0);//等待接收结束read_time[k-1]=SSPBUF;NOP();NOP();PEN=1;//停止信号while(PEN==1);}}void display_time(){lcd_write(0x80,0);lcd_write(0x32,1);lcd_write(0x30,1);lcd_write(0x30+read_time[6]/16,1);//年lcd_write(0x30+read_time[6]%16,1);lcd_write('-',1);lcd_write(0x30+read_time[5]/16,1);//月lcd_write(0x30+read_time[5]%16,1);lcd_write('-',1);lcd_write(0x30+read_time[4]/16,1);//日lcd_write(0x30+read_time[4]%16,1);lcd_write(0x80+0x0d,0);switch(read_time[3]){case 1:lcd_write('M',1);lcd_write('O',1);lcd_write('N',1);break;case 2:lcd_write('T',1);lcd_write('U',1);lcd_write('E',1);break;case 3:lcd_write('W',1);lcd_write('E',1);lcd_write('D',1);break;case 4:lcd_write('T',1);lcd_write('H',1);lcd_write('U',1);break;case 5:lcd_write('F',1);lcd_write('R',1);lcd_write('I',1);break;case 6:lcd_write('S',1);lcd_write('A',1);lcd_write('T',1);break;case 7:lcd_write('S',1);lcd_write('U',1);lcd_write('N',1);break;lcd_write(0x80+0x40,0);lcd_write(0x30+read_time[2]/16,1);//时lcd_write(0x30+read_time[2]%16,1);lcd_write(':',1);lcd_write(0x30+read_time[1]/16,1); //分lcd_write(0x30+read_time[1]%16,1);lcd_write(':',1);lcd_write(0x30+read_time[0]/16,1); //秒lcd_write(0x30+read_time[0]%16,1);NOP();NOP();cent=read_temp();lcd_write(0x80+0x4b,0);lcd_write(0x30+cent/10,1);lcd_write(0x30+cent%10,1);lcd_write(0xdf,1);lcd_write('C',1);if((shi==(read_time[2]/16*10+read_time[2]%16))&&(fen<=(read_ti me[1]/16*10+read_time[1]%16))&&((read_time[1]/16*10+read_time[1] %16)<(fen+alarm_time)))naoling();}if((shi==(read_time[2]/16*10+read_time[2]%16))&&(fen+reapeat_fe n<=(read_time[1]/16*10+read_time[1]%16))&&((read_time[1]/16*10+re ad_time[1]%16)<(fen+alarm_time+reapeat_fen))){naoling();}if((shi==(read_time[2]/16*10+read_time[2]%16))&&(fen+2*reapeat _fen<=(read_time[1]/16*10+read_time[1]%16))&&((read_time[1]/16*10 +read_time[1]%16)<(fen+alarm_time+2*reapeat_fen))){naoling();}if((shi==(read_time[2]/16*10+read_time[2]%16))&&(fen+3*reapeat _fen<=(read_time[1]/16*10+read_time[1]%16))&&((read_time[1]/16*10 +read_time[1]%16)<(fen+alarm_time+3*reapeat_fen))){naoling();}if((shi==(read_time[2]/16*10+read_time[2]%16))&&(fen+4*reapeat_fen<=(read_time[1]/16*10+read_time[1]%16))&&((read_time[1]/16*10 +read_time[1]%16)<(fen+alarm_time+4*reapeat_fen))){naoling();}}void setting_time(){uchar l,s2_value,setting_flag;if(s2==0){delayms(10);if(s2==0){s2_value++;setting_flag = 1;while(s2==0);//松手检测for(l=0;l<7;l++)//存储当前时间数据//年星期月日时分秒{set_time[l]=read_time[l]/16*10+read_time[l]%16;}while(setting_flag){if(s2==0){delayms(5);if(s2==0){s2_value++;while(s2==0);//松手检测}}if(s2_value==1){lcd_write(0x83,0);//指向年份lcd_write(0x0f,0);//显示游标并闪烁if(s3==0){delayms(5);if(s3==0){set_time[6]++;if(set_time[6]==100){set_time[6]=0;}lcd_write(0x82,0);lcd_write(0x30+set_time[6]/10,1);lcd_write(0x30+set_time[6]%10,1);lcd_write(0x83,0);//指向年份while(s3==0);}}if(s4==0){delayms(5);{set_time[6]--;if(set_time[6]==-1){set_time[6]=99;}lcd_write(0x82,0);lcd_write(0x30+set_time[6]/10,1);lcd_write(0x30+set_time[6]%10,1);lcd_write(0x83,0);//指向年份while(s4==0);}}}if(s2_value==2){lcd_write(0x86,0);//指向月份if(s3==0){delayms(5);{set_time[5]++;if(set_time[5]==13){set_time[5]=1;}lcd_write(0x85,0);lcd_write(0x30+set_time[5]/10,1);lcd_write(0x30+set_time[5]%10,1);lcd_write(0x86,0);//指向月份while(s3==0);}}if(s4==0){delayms(5);if(s4==0){set_time[5]--;{set_time[5]=12;}lcd_write(0x85,0);lcd_write(0x30+set_time[5]/10,1);lcd_write(0x30+set_time[5]%10,1);lcd_write(0x86,0);//指向月份while(s4==0);}}}if(s2_value==3){lcd_write(0x89,0);//指向日if(s3==0){delayms(5);if(s3==0){set_time[4]++;{set_time[4]=1;}lcd_write(0x88,0);lcd_write(0x30+set_time[4]/10,1);lcd_write(0x30+set_time[4]%10,1);lcd_write(0x89,0);//指向日while(s3==0);}}if(s4==0){delayms(5);if(s4==0){set_time[4]--;if(set_time[4]==0){set_time[4]=31;lcd_write(0x88,0);lcd_write(0x30+set_time[4]/10,1);lcd_write(0x30+set_time[4]%10,1);lcd_write(0x89,0);//指向日while(s4==0);}}}if(s2_value==4){lcd_write(0x8f,0);//指向星期if(s3==0){delayms(5);if(s3==0){set_time[3]++;if(set_time[3]==8)set_time[3]=1;}switch(set_time[3]){case1:lcd_write(0x8d,0);lcd_write('M',1);lcd_write('O',1);lcd_write('N',1);bre ak;case2:lcd_write(0x8d,0);lcd_write('T',1);lcd_write('U',1);lcd_write('E',1);brea k;case3:lcd_write(0x8d,0);lcd_write('W',1);lcd_write('E',1);lcd_write('D',1);bre ak;case4:lcd_write(0x8d,0);lcd_write('T',1);lcd_write('H',1);lcd_write('U',1);brea k;case5:lcd_write(0x8d,0);lcd_write('F',1);lcd_write('R',1);lcd_write('I',1);break ;case6:lcd_write(0x8d,0);lcd_write('S',1);lcd_write('A',1);lcd_write('T',1);break;case7:lcd_write(0x8d,0);lcd_write('S',1);lcd_write('U',1);lcd_write('N',1);brea k;}lcd_write(0x8f,0);//指向星期while(s3==0);}}if(s4==0){delayms(5);if(s4==0){set_time[3]--;if(set_time[3]==0){set_time[3]=7;}switch(set_time[3])case1:lcd_write(0x8d,0);lcd_write('M',1);lcd_write('O',1);lcd_write('N',1);bre ak;case2:lcd_write(0x8d,0);lcd_write('T',1);lcd_write('U',1);lcd_write('E',1);brea k;case3:lcd_write(0x8d,0);lcd_write('W',1);lcd_write('E',1);lcd_write('D',1);bre ak;case4:lcd_write(0x8d,0);lcd_write('T',1);lcd_write('H',1);lcd_write('U',1);brea k;case5:lcd_write(0x8d,0);lcd_write('F',1);lcd_write('R',1);lcd_write('I',1);break ;case6:lcd_write(0x8d,0);lcd_write('S',1);lcd_write('A',1);lcd_write('T',1);brea k;case7:lcd_write(0x8d,0);lcd_write('S',1);lcd_write('U',1);lcd_write('N',1);brea k;lcd_write(0x8f,0);//指向星期while(s4==0);}}}if(s2_value==5){lcd_write(0x80+0x41,0);//指向小时if(s3==0){delayms(5);if(s3==0){set_time[2]++;if(set_time[2]==24){set_time[2]=0;}lcd_write(0x80+0x40,0);lcd_write(0x30+set_time[2]/10,1);lcd_write(0x30+set_time[2]%10,1);lcd_write(0x80+0x41,0);//指向小时while(s3==0);}}if(s4==0){delayms(5);if(s4==0){set_time[2]--;if(set_time[2]==-1){set_time[2]=23;}lcd_write(0x80+0x40,0);lcd_write(0x30+set_time[2]/10,1);lcd_write(0x30+set_time[2]%10,1);lcd_write(0x80+0x41,0);//指向小时while(s4==0);}}}if(s2_value==6){lcd_write(0x80+0x44,0);//指向分钟if(s3==0){delayms(5);if(s3==0){set_time[1]++;if(set_time[1]==60){set_time[1]=0;}lcd_write(0x80+0x43,0);lcd_write(0x30+set_time[1]/10,1);lcd_write(0x30+set_time[1]%10,1);lcd_write(0x80+0x44,0);//指向分钟while(s3==0);}}if(s4==0){delayms(5);if(s4==0){set_time[1]--;if(set_time[1]==-1){set_time[1]=59;}lcd_write(0x80+0x43,0);lcd_write(0x30+set_time[1]/10,1);lcd_write(0x30+set_time[1]%10,1);lcd_write(0x80+0x44,0);//指向分钟while(s4==0);}}}if(s2_value==7){lcd_write(0x80+0x47,0);//指向秒if(s3==0){delayms(5);if(s3==0){set_time[0]++;if(set_time[0]==60){set_time[0]=0;}lcd_write(0x80+0x46,0);lcd_write(0x30+set_time[0]/10,1);lcd_write(0x30+set_time[0]%10,1);lcd_write(0x80+0x47,0);//指向分钟while(s3==0);}}if(s4==0){delayms(5);if(s4==0){set_time[0]--;if(set_time[0]==-1){set_time[0]=59;}lcd_write(0x80+0x46,0);lcd_write(0x30+set_time[0]/10,1);lcd_write(0x30+set_time[0]%10,1);lcd_write(0x80+0x47,0);//指向分钟while(s4==0);}}}if(s2_value==8)//这里注意?{s2_value=0;lcd_write(0x0c,0);setting_flag=0;time_csh();}}}}}void naozhong(){write_string(0x80,alarm);lcd_write(0x30+shi/10,1);lcd_write(0x30+shi%10,1);lcd_write('-',1);lcd_write(0x30+fen/10,1);lcd_write(0x30+fen%10,1);write_string(0x80+0x40,mode);lcd_write(0x30+alarm_time,1);write_string(0x80+0x47,rpt);lcd_write(0x30+reapeat_fen/10,1);lcd_write(0x30+reapeat_fen%10,1);write_string(0x80+0x4d,min);}uchar s1_scan(){if(s1==0){delayms(5);if(s1==0){s1_num++;if(s1_num==2){s1_num=0;s2_num=0;lcd_write(0x0c,0);}while(s1==0);lcd_write(0x01,0);if(s1_num==1){naozhong();lcd_write(0x0f,0);}}}return s1_num;}void setting_naozhong(){if(s2==0){delayms(5);if(s2==0){s2_num++;if(s2_num==4){s2_num=0;}while(s2==0);}}switch(s2_num){case 0:{lcd_write(0x8c,0);if(s3==0){delayms(5);if(s3==0){shi++;if(shi==24){shi=0;}lcd_write(0x8b,0);lcd_write(0x30+shi/10,1);lcd_write(0x30+shi%10,1);lcd_write(0x8c,0);//指向小时while(s3==0);}}if(s4==0){delayms(5);if(s4==0){shi--;if(shi==-1){shi=23;}lcd_write(0x8b,0);lcd_write(0x30+shi/10,1);lcd_write(0x30+shi%10,1);lcd_write(0x8c,0);//指向小时while(s4==0);}}break;}case 1:{lcd_write(0x8f,0);if(s3==0){delayms(5);if(s3==0){fen++;if(fen==60){fen=0;}lcd_write(0x8e,0);lcd_write(0x30+fen/10,1);lcd_write(0x30+fen%10,1);lcd_write(0x8f,0);//指向小时while(s3==0);}}if(s4==0){delayms(5);if(s4==0){fen--;if(fen==-1){fen=59;}lcd_write(0x8e,0);lcd_write(0x30+fen/10,1);lcd_write(0x30+fen%10,1);lcd_write(0x8f,0);//指向小时while(s4==0);}}break;}case 2:{lcd_write(0x80+0x45,0);if(s3==0){delayms(5);if(s3==0){alarm_time++;if(alarm_time==10){alarm_time=1;}lcd_write(0x30+alarm_time,1);lcd_write(0x80+0x45,0);//指向小时while(s3==0);}}if(s4==0){delayms(5);if(s4==0){alarm_time--;if(alarm_time==0){alarm_time=9;}lcd_write(0x30+alarm_time,1);lcd_write(0x80+0x45,0);//指向小时while(s4==0);}}break;}case 3:{lcd_write(0x80+0x4c,0);if(s3==0){delayms(5);if(s3==0){reapeat_fen++;if(reapeat_fen==60){reapeat_fen=0;}lcd_write(0x80+0x4b,0);lcd_write(0x30+reapeat_fen/10,1);lcd_write(0x30+reapeat_fen%10,1);lcd_write(0x80+0x4c,0);//指向小时while(s3==0);}}if(s4==0){delayms(5);if(s4==0){reapeat_fen--;if(reapeat_fen==-1){reapeat_fen=59;}lcd_write(0x80+0x4b,0);lcd_write(0x30+reapeat_fen/10,1);lcd_write(0x30+reapeat_fen%10,1);lcd_write(0x80+0x4c,0);//指向小时while(s4==0);}}break;}default:break;}}void main(){PORT_INIT();LCD_INIT();IIC_INIT();time_csh();while(1){switch(s1_scan()){case 0:read_ds1307();display_time();setting_time();break;case 1:setting_naozhong();break;default:break;}} }。

PIC16F877A定时器的学习

PIC16F877A定时器的学习

PIC16F877A定时器的学习由于实时数据的仿真需要用到定时器产生数据,今天晚上完成PIC16F877A 产生正弦波形,并将波形数据发送到上位机!这是一个三角波的仿真程序,并通过串口发送到上位机#include #include #include#include “main.h”#include“t232.h”#include“lcd.h”#include“timer.h”//define global variablebank1 uchar flag =0 ;//利用flag 判断中断时间是否到了!bank1 char dat[6] ;bank2 char str[]=“shan dong qing gong ye xue yuan”;bank2 char str1[]=“Starting........”;bank2 char str2[]=“Capturing.......”;bank2 char str3[]=“Stop..........” ;//bank2 float test = 0;//bank2 float t1 ;bank2 uchar t1 =0 ;bank2 uchar t2=0 ;bank1 uchar state = READY ;//当前状态bank1 uchar frame[3] ;//帧缓冲bank1 uchar temp ;//ms 级延时程序void DelayMS(uint ms){ uint i; while(ms--){ for(i=0;i//10us 级延时程序void Delay10US(uint us){ uchar i; for(i=0;iwhile(1) {while((t1>=-20)&&(state==CAPTURE)){t1++ ;sprintf(dat,”(%d)”,t1) ;send_str(dat);if(t1==20)break ;}while((t1}tips:感谢大家的阅读,本文由我司收集整编。

PIC16F877 EEPROM读写实验

PIC16F877 EEPROM读写实验

PIC16F877 EEPROM每一个单元的读/写所用时间典型值为:4ms,最大值为8ms。

在烧写每个EEPROM 单元过程中,需要CPU插入等待时间,既可利用中断功能,也可利用软件查询方式来解决。

在此我们利用了软件查询方式,循环检测WR烧写控制位兼烧写完成标志位。

程序如下:;实战《16F877内部EEPROM读/写实验》;本实战的目的是让大家熟悉PIC16F87X内部EEPROM的读/写方法;项目实现的功能:对于地址为00H-3FH的64个EEPROM数据存储单元,分;别将数据0-63依次烧写进去,然后再循环读出,显示在LED数码管上;程序清单如下:;************************************INCLUDE"P16F877.INC"STATUS EQU 3H ;定义状态寄存器地址RP0 EQU 5H ;定义页选位RP0的位地址RP1 EQU 6H ;定义页选位RP1的位地址Z EQU 2H ;定义0状态位的位地址PORTC EQU 7H ;定义RC口数据寄存器地址PORTD EQU 8HTRISC EQU 87H ;定义RC口方向控制寄存器地址TRISD EQU 88HEECON1 EQU 18CH ;定义写控制寄存器1的地址EECON2 EQU 18DH ;定义写控制寄存器2的地址EEDATA EQU 10CH ;定义读/写数据寄存器地址EEADR EQU 10DH ;定义读/写地址寄存器地址RD EQU 0 ;定义读启动控制位位地址WR EQU 1 ;定义写启动控制位位地址WREN EQU 2 ;定义写使能控制位位地址EEPGD EQU 7 ;定义访问目标选择控制位位址F EQU 1 ;定义目标寄存器为RAM的指示符W EQU 0 ;定义目标寄存器为W的指示符ADDR EQU 70H ;定义地址变量DATA1 EQU 71H ;定义数据变量;*************************************ORG 0000H ;NOP ;放置一条ICD必须的空操作指令GOTO MAIN ;ORG 0008H ;MAINBCF STATUS,RP1 ;选体1为当前体BSF STATUS,RP0 ;MOVLW 00H ;设定RC全部为输出MOVWF TRISC ;BSF STATUS,RP1 ;体3为当前体CLRF ADDR ;地址变量清0CLRF DATA1 ;数据变量清0WRITEBSF STATUS,RP1 ;选定体3BTFSC EECON1,WR ;上一次写操作是否完成GOTO $-1 ;否!返回继续检测BCF STATUS,RP0 ;选定体2MOVF ADDR,W ;取地址MOVWF EEADR ;送地址寄存器MOVF DATA1,W ;取数据MOVWF EEDATA ;送数据寄存器BSF STATUS,RP0 ;选定体3BCF EECON1,EEPGD ;选定EEPROM为访问对向BSF EECON1,WREN ;开放写操作使能控制MOVLW 55H ;MOVWF EECON2 ;送55H到寄存器EECON2(读写内部EEPROM,这句是固定的) MOVLW 0AAH ;MOVWF EECON2 ;送AAH到寄存器EECON2(读写内部EEPROM,这句是固定的) BSF EECON1,WR ;启动写操作BCF EECON1,WREN ;禁止写操作发生INCF DATA1,F ;数据递增INCF ADDR,F ;地址递增MOVF ADDR,W ;XORLW D'64' ;将当前地址与64比较BTFSS STATUS,Z ;检测=64否GOTO WRITE ;否!继续写后面单元READ1DECF ADDR,F ;地址递减BCF STATUS,RP0 ;选体2为当前体BSF STATUS,RP1 ;MOVF ADDR,W ;取地址MOVWF EEADR ;送地址寄存器BSF STATUS,RP0 ;选体3为当前体BCF EECON1,EEPGD ;选定EEPROM为访问对象BSF EECON1,RD ;启动读操作BCF STATUS,RP0 ;体2为当前体MOVF EEDATA,W ;取数据BCF STATUS,RP1 ;体0为当前体MOVWF PORTC ;送显LEDCALL DELAY ;调用廷时子程序MOVF ADDR,F ;检测当前地址BTFSS STATUS,Z ;是否为0?是!跳一步GOTO READ1 ;否!返回继续读出和显示READ2INCF ADDR,F ;地址递增BCF STATUS,RP0 ;选体2为当前体BSF STATUS,RP1 ;MOVF ADDR,W ;取地址MOVWF EEADR ;送地址寄存器BSF STATUS,RP0 ;选体3为当前体BCF EECON1,EEPGD ;选定EEPROM为访问对象BSF EECON1,RD ;启动读操作BCF STATUS,RP0 ;体2为当前体MOVF EEDATA,W ;取数据BCF STATUS,RP1 ;体0为当前体CALL LED_SHOW ;送数码管显示CALL DELAY ;调用廷时子程序MOVF ADDR,W ;检测当前地址与64比较XORLW D'64' ;BTFSS STATUS,Z ;是否等于64GOTO READ2 ;否!返回继续读出和显示GOTO READ1 ;返回大循环起点;******************************************DELAYMOVLW 0 ;MOVWF 72H ;将外层循环参数值256送外层循环寄存器DELAY1MOVLW 0 ;将内层循环参数值256送内层循环寄存器MOVWF 73H ;DECFSZ 73H,1 ;递减廷时程序GOTO $-1 ;DECFSZ 72H,1 ;GOTO DELAY1 ;RETURN;==========================================================; 2位LED共阳数码管显示模块; 入口: 待显示的数据在W中;----------------------------------------------------------LCD1 EQU 20H ;定义显示缓存单元LCD2 EQU 21HW_TEMP EQU 22H ;保护单元STATUS_TEMP EQU 23HCOUNT0 EQU 24HCOUNT1 EQU 25HCOUNT2 EQU 26HLED_SHOW; MOVLW 7FH ;;;;;;;MOVWF LCD1 ;现场保护,将W的内容暂存于LCD1MOVWF W_TEMP ;现场保护[W-->W_TEMP]SWAPF STATUS,W ;用SWAPF才不会影响标志位[W与STATUS高低4位交换] MOVWF STATUS_TEMP ;将W和STATUS存入各保护寄存器[STATUS-->STATUS_TEMP]BCF STATUS,RP1 ;选体1为当前体BSF STATUS,RP0 ;MOVLW 00HMOVWF TRISD ;设RD为输出口BCF STATUS,RP0 ;恢复体0; MOVWF LCD1 ;W-->LCD1MOVF LCD1,W ;LCD1-->WANDLW B'11110000' ;0FH与W相"与"后送WMOVWF LCD2 ;W-->FSWAPF LCD2 ;F高低4位互换MOVF LCD2,WCALL CONVERT ;绎码MOVWF PORTCMOVLW 02HMOVWF PORTD ;开LCD十位CALL DELAY2 ;延时MOVLW 0HMOVWF PORTD ;关LCD个位MOVF LCD1,W ;F-->WANDLW B'00001111' ;0FH与W相"与"后送WCALL CONVERT ;绎码MOVWF PORTCMOVLW 01HMOVWF PORTD ;开LCD个位CALL DELAY2 ;延时MOVLW 0HMOVWF PORTD ;关LCD个位SWAPF STATUS_TEMP,W ;恢复中断前STATUS,W的值MOVWF STATUSSWAPF W_TEMP,F ;W_TEMP高低4位互换SWAPF W_TEMP,W ;(用SWAPF才不会影响STATUS的值)RETURN ;子程序返回;==========================================================;-------------------- 共阳顺序7段数码管段码 --------------- CONVERT ;取数码管段码ADDWF PCL,1 ;地址偏移量加当前PC值TABLE RETLW 0C0H ;0RETLW 0F9H ;1 RETLW 0A4H ;2RETLW 0B0H ;3RETLW 99H ;4RETLW 92H ;5RETLW 82H ;6RETLW 0F8H ;7RETLW 80H ;8RETLW 90H ;9RETLW 88H ;ARETLW 83H ;bRETLW 0C6H ;cRETLW 0A1H ;dRETLW 86H ;ERETLW 8EH ;F; RETLW 7FH ;. 小数点RETLW 00H ;结束符;---------------------------------------------------------- ;--------------------------- 廷时子程序 ----------------- DELAY2MOVLW .2 ;设置延时常数 [.2--即为2] MOVWF COUNT0L1MOVLW .50 ;MOVWF COUNT1L2MOVLW .100 ;MOVWF COUNT2L3DECFSZ COUNT2,1 ;递减循环GOTO L3 ;DECFSZ COUNT1,1 ;GOTO L2 ;DECFSZ COUNT0,1 ;GOTO L1 ;RETLW 0;========================================================== END。

用C语言写的一个PIC16F877的时闹钟程序

用C语言写的一个PIC16F877的时闹钟程序

用C语言写的一个PIC16F877的时闹钟程序单片机用16F877,主时钟用20MHz,用32768作定时时间。

可以实现2路定闹,每一路都可分别设置和开关,采用4x4键盘,16x2的字符型LCD显示。

连线在程序开头有说明。

程序的功能:(1)上电后LCD背光打开,并显示倒计时5秒,然后时钟开始工作。

(2)用模式键(*)切换模式,如显示时间、日期、闹钟1、闹钟2等,并且可以用上、下键控制加1、减1或是闹钟的On、Off。

(3)原程序有16个键,包括0~9数字键,可以直接输入要设置的时间值,但后来将数字键取消了,你仍然可以通过修改程序的部分注释恢复此功能。

(4)闹钟有2路,时间到后闹2分钟,可按任意键取消本次闹钟。

闹钟响时有2种音调,是用PIC的PWM实现的。

(5)按任意键可打开背光,1分钟后自动关闭背光。

(6)RA0~RA3为按键扫描输入,应接下拉电阻。

主程序// FileName: Main.c// MCU: Microchip PIC16F877// Tool: CCS-C compiler// Author: KingEDA, MSN:kingeda@, skype:kingeda, E-mail:kingeda@// Website: // Description:// A timer program// Ver 0.1: 2003-03-31, all clock function with date display, 2 way alarm.// Ver 0.2: 2003-05-05, (1) Alarm default is on,modify alarm1 time to 7:00:00,// and alarm2 to 13:30:00.// (2) Backlight will be enabled when alarming.// (3) Automatic adjust day(28,30,31).// (4) Automatic move cursor to next location when set item.// PIN Connection:// RC0~1 : 32768Hz crystal// RC2 : Buzzer// RC3 : LCD Back Light,drive a PNP BJT// RD0~RD7 : to LCD DB0~DB7// RA0~RA3 : keypad col in// RC4~RC7 : keypad line out// 7 8 9 #// 4 5 6 ↑// 1 2 3 ↓// 0 ←→*// RE0 : LCD RS// RE1 : LCD RW// RE2 : LCD E#include "my16f877.h"#device ICD=true//#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT #use delay(clock = 24000000)//#use fast_io(C)#use fast_io(E)#define lcd_busy (lcd_read_addr()&0x80) == 0x80#define time_start_addr 0x80+0x04#define time_hourh_addr time_start_addr#define time_hourl_addr time_start_addr+1#define time_minuteh_addr time_start_addr+3#define time_minutel_addr time_start_addr+4#define time_secondh_addr time_start_addr+6#define time_secondl_addr time_start_addr+7#define key_0 0x11#define key_1 0x21#define key_2 0x22#define key_3 0x24#define key_4 0x41#define key_5 0x42#define key_6 0x44#define key_7 0x81#define key_8 0x82#define key_9 0x84#define key_left 0x12#define key_right 0x14#define key_up 0x48#define key_down 0x28#define key_mode 0x18#define key_cancel 0x88char StrPower1[] = " * Power on * ";char StrSetTime[] = " * Adjust time* ";char StrSetDate[] = " * Adjust date* ";char StrAlarm1[] = " * Set alarm 1* ";char StrAlarm2[] = " * Set alarm 2* ";unsigned char PORTC_MAP;#bit BackLightEn = PORTC_MAP.3unsigned char BackLightTimer;int1 led;#bit lcd_rs = PORTE.0#bit lcd_rw = PORTE.1#bit lcd_e = PORTE.2#byte lcd_bus = PORTD#byte lcd_dir = TRISD#define PWM_on 0x0c#define PWM_off 0x00#define PWM_period 200#define PWM_DC 100unsigned char lcd_addr;unsigned char KeyLine;unsigned char KeyOld;unsigned char KeyNew;struct mTime {unsigned char hourh; // hour,0~23unsigned char hourl;unsigned char minuteh; // minute,0~59unsigned char minutel;unsigned char secondh; // second,0~59unsigned char secondl;};struct mTime CurrentTime = {1,2,0,0,0,0};struct mTime AlarmTime1 = {0,7,0,0,0,0}; // 07:00:00 struct mTime AlarmTime2 = {1,3,3,0,0,0}; // 13:30:00 unsigned char AlarmStatus;#bit Alarm1Enable = AlarmStatus.0#bit Alarm2Enable = AlarmStatus.1#bit Alarm1Alarm = AlarmStatus.2#bit Alarm2Alarm = AlarmStatus.3unsigned char Alarm1Cnt; // alarm1 second count unsigned char Alarm2Cnt;unsigned char CurrentMode;#define mode_time 0#define mode_set_time 1#define mode_set_date 2#define mode_set_alarm1 3#define mode_set_alarm2 4unsigned char adjust_item;struct mDate {unsigned char year1; //unsigned char year2;unsigned char year3;unsigned char year4;unsigned char monthh;unsigned char monthl;unsigned char dayh;unsigned char dayl;};struct mDate CurrentDate = {2,0,0,3,0,1,0,1}; unsigned char *pStr;// ------------------------------------------------------- unsigned char lcd_read_addr(){unsigned char ch;lcd_dir = 0xff; // read from lcdlcd_rs = 0;lcd_rw = 1; // instlcd_e = 1;#asmnopnopnop#endasmch = lcd_bus;lcd_e = 0;lcd_dir = 0x00; // set write to lcdreturn ch;}// ------------------------------------------------------- unsigned char lcd_write_data(unsigned char ch) {while (lcd_busy){ restart_wdt(); }lcd_rs = 1; // datalcd_rw = 0; // writelcd_bus = ch; // write outlcd_e = 1;#asmnopnopnop#endasmlcd_e = 0;return 'Y';}// ------------------------------------------------------- unsigned char lcd_write_inst(unsigned char ch) {while (lcd_busy){ restart_wdt(); }lcd_rs = 0; // instlcd_rw = 0; // writelcd_bus = ch;lcd_e = 1;#asmnopnopnop#endasmlcd_e = 0;return 'Y';}// ------------------------------------------------------- unsigned char lcd_read_data(){unsigned char ch;while (lcd_busy){ restart_wdt(); }lcd_dir = 0xff; // read from lcdlcd_rs = 1; // datalcd_rw = 1; // readlcd_e = 1;#asmnopnopnop#endasmch = lcd_bus; // read inlcd_e = 0;lcd_dir = 0x00; // set write to lcdreturn ch;}// ------------------------------------------------------- void lcd_init(){unsigned char Tempch;lcd_addr = 0;delay_ms(100);Tempch = 0x38; // 1-line mode,5x8 dotslcd_write_inst(Tempch); // Function setTempch = 0x0f; // lcd on,cursor on,blink onlcd_write_inst(Tempch); // Display on/offTempch = 0x06; // Increment mode,Entire shift offlcd_write_inst(Tempch);Tempch = 0x01; // clear displaylcd_write_inst(Tempch);delay_ms(3);}// -------------------------------------------------------//#int_timer1//void timer1_interrupt(void)#int_ccp2void ccp2_interrupt(void){//TMR1H = 0x80;if (CurrentTime.secondl==9){CurrentTime.secondl=0;if (CurrentTime.secondh==5){CurrentTime.secondh=0;if (CurrentTime.minutel==9){CurrentTime.minutel=0;if (CurrentTime.minuteh==5){CurrentTime.minuteh=0;if (CurrentTime.hourl==9){CurrentTime.hourl=0;CurrentTime.hourh++;}else if((CurrentTime.hourl==3) && (CurrentTime.hourh==2)){CurrentTime.hourl=0;CurrentTime.hourh=0;if ((((CurrentDate.dayl == 8) || (CurrentDate.dayl == 9)) && (CurrentDate.dayh == 2) && (CurrentDate.monthl == 2) && (CurrentDate.monthh == 0)) ||((CurrentDate.dayl == 0) && (CurrentDate.dayh == 3) && ((((CurrentDate.monthl == 4) || (CurrentDate.monthl == 6)|| (CurrentDate.monthl == 9)) && (CurrentDate.monthh == 0)) || ((CurrentDate.monthl == 1) && (CurrentDate.monthh == 1)))) ||((CurrentDate.dayl == 1) && (CurrentDate.dayh == 3))){CurrentDate.dayl=1;CurrentDate.dayh=0;if ((CurrentDate.monthl == 2) && (CurrentDate.monthh == 1)){CurrentDate.monthl = 1;CurrentDate.monthh = 0;if (CurrentDate.year4 == 9){CurrentDate.year4 = 0;if (CurrentDate.year3 == 9){CurrentDate.year3 = 0;if (CurrentDate.year2 == 9){CurrentDate.year2 = 0;CurrentDate.year1++;}elseCurrentDate.year2++;}elseCurrentDate.year3++;}elseCurrentDate.year4++;}else if(CurrentDate.monthl == 9){CurrentDate.monthl = 0;CurrentDate.monthh++;}elseCurrentDate.monthl++;}else if(CurrentDate.dayl == 9){CurrentDate.dayl=0;CurrentDate.dayh++;}elseCurrentDate.dayl++;}elseCurrentTime.hourl++;}elseCurrentTime.minuteh++;}elseCurrentTime.minutel++;}elseCurrentTime.secondh++;}elseCurrentTime.secondl++;if ((Alarm1Alarm == false) & (Alarm2Alarm == false)){led = 0;CCP1CON = PWM_off;}else{if (led == 1){led = 0;PR2 = PWM_period; // set pwm periodCCPR1L = PWM_DC; // set pwm duty cycle//CCP1CON = PWM_on;}else{led = 1;PR2 = PWM_period/2; // set pwm periodCCPR1L = PWM_DC/2; // set pwm duty cycle//CCP1CON = PWM_off;}}Alarm1Cnt++;Alarm2Cnt++;if (BackLightEn == 0)if (((BackLightTimer++)>=60) & (Alarm1Alarm == false) & (Alarm1Alarm == false))BackLightEn = 1; // disable backlight PORTC = PORTC_MAP;//TMR1IF = 0;//PIR1 = PIR2 = 0x00;CCP2IF = 0;}// ------------------------------------------------------- unsigned char get_key(void){unsigned char key_in,tmp;TRISC = 0x03;KeyLine = 0xf0;PORTC = KeyLine | PORTC_MAP;#asmnopnopnop#endasmif ((PORTA & 0x0f) != 0){tmp = 0x10;for (KeyLine = tmp;KeyLine!=0;KeyLine = tmp){PORTC = KeyLine | PORTC_MAP;tmp = KeyLine <<1;#asmnopnopnop#endasmkey_in = PORTA & 0x0f;if (key_in != 0){return (key_in | KeyLine);}}return 0;}elsereturn 0;}// -------------------------------------------------------void set_mode(void){if (CurrentMode == mode_set_alarm2)CurrentMode = mode_time;else{CurrentMode++;adjust_item = 0;}lcd_write_inst(0x01); // clear LCD displaylcd_write_inst(time_start_addr); // set LCD line1 if (CurrentMode == mode_set_time){lcd_write_data(CurrentTime.hourh + '0');lcd_write_data(CurrentTime.hourl + '0');lcd_write_data(':');lcd_write_data(CurrentTime.minuteh + '0');lcd_write_data(CurrentTime.minutel + '0');lcd_write_data(':');lcd_write_data(CurrentTime.secondh + '0');lcd_write_data(CurrentTime.secondl + '0');pStr = StrSetTime;}else if(CurrentMode == mode_set_date){lcd_write_data(CurrentDate.year1 + '0');lcd_write_data(CurrentDate.year2 + '0');lcd_write_data(CurrentDate.year3 + '0');lcd_write_data(CurrentDate.year4 + '0');lcd_write_data('/');lcd_write_data(CurrentDate.monthh + '0');lcd_write_data(CurrentDate.monthl + '0');lcd_write_data('/');lcd_write_data(CurrentDate.dayh + '0');lcd_write_data(CurrentDate.dayl + '0');pStr = StrSetDate;}else if(CurrentMode == mode_set_alarm1){lcd_write_data(AlarmTime1.hourh + '0');lcd_write_data(AlarmTime1.hourl + '0');lcd_write_data(':');lcd_write_data(AlarmTime1.minuteh + '0');lcd_write_data(AlarmTime1.minutel + '0');lcd_write_data(':');lcd_write_data(AlarmTime1.secondh + '0');lcd_write_data(AlarmTime1.secondl + '0');lcd_write_data(' ');lcd_write_data('O');if (Alarm1Enable){lcd_write_data('n');}else{lcd_write_data('f');lcd_write_data('f');}pStr = StrAlarm1;Alarm1Cnt =0;}else if(CurrentMode == mode_set_alarm2) {lcd_write_data(AlarmTime2.hourh + '0');lcd_write_data(AlarmTime2.hourl + '0');lcd_write_data(':');lcd_write_data(AlarmTime2.minuteh + '0');lcd_write_data(AlarmTime2.minutel + '0');lcd_write_data(':');lcd_write_data(AlarmTime2.secondh + '0');lcd_write_data(AlarmTime2.secondl + '0');lcd_write_data(' ');lcd_write_data('O');if (Alarm2Enable){lcd_write_data('n');}else{lcd_write_data('f');lcd_write_data('f');}pStr = StrAlarm2;Alarm2Cnt = 0;}lcd_write_inst(0xc0); // set LCD line2 if (CurrentMode != mode_time){for (;*pStr!=0;pStr++){ // write hint messagelcd_write_data(*pStr);}lcd_write_inst(0x0f); // LCD cursor onlcd_write_inst(time_start_addr); // move cursor to start }else // time mode,write date to second line{lcd_write_inst(0x0c); // LCD sursor off/* lcd_write_inst(0xc0 + 3); // set date start address lcd_write_data(CurrentDate.year1 + '0');lcd_write_data(CurrentDate.year2 + '0');lcd_write_data(CurrentDate.year3 + '0');lcd_write_data(CurrentDate.year4 + '0');lcd_write_data('/');lcd_write_data(CurrentDate.monthh + '0');lcd_write_data(CurrentDate.monthl + '0');lcd_write_data('/');lcd_write_data(CurrentDate.dayh + '0');lcd_write_data(CurrentDate.dayl + '0');*/ }if (CurrentMode == mode_set_time){lcd_write_inst(time_start_addr); // move cursor to start }else if (CurrentMode == mode_set_date){lcd_write_inst(time_start_addr); // move cursor to start }else if (CurrentMode == mode_set_alarm1){lcd_write_inst(time_secondl_addr+3);adjust_item = 6;}else if (CurrentMode == mode_set_alarm2){lcd_write_inst(time_secondl_addr+3);adjust_item = 6;}else{lcd_write_inst(0x0c); // LCD cursor off}}// ------------------------------------------------------- void set_date(void){if (adjust_item == 0) // adjust year{if ((KeyNew >=0) & (KeyNew <= 9)){CurrentDate.year1 = KeyNew;lcd_write_data(CurrentDate.year1 + '0');//lcd_write_inst(time_start_addr);adjust_item ++;}else if (KeyNew == key_left){adjust_item = 7;lcd_write_inst(time_start_addr + 9);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 1);}}else if(adjust_item == 1){if ((KeyNew >=0) & (KeyNew <= 9)){CurrentDate.year2 = KeyNew;lcd_write_data(CurrentDate.year2 + '0');//lcd_write_inst(time_start_addr + 1);adjust_item ++;}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 0);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 2);}}else if(adjust_item == 2){if ((KeyNew >=0) & (KeyNew <= 9)){CurrentDate.year3 = KeyNew;lcd_write_data(CurrentDate.year3 + '0');//lcd_write_inst(time_start_addr + 2);adjust_item ++;}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 1);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 3);}}else if(adjust_item == 3){if ((KeyNew >=0) & (KeyNew <= 9)){CurrentDate.year4 = KeyNew;lcd_write_data(CurrentDate.year4 + '0');//lcd_write_inst(time_start_addr + 3);adjust_item ++;lcd_write_inst(time_start_addr + 5);}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 2);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 5);}}else if(adjust_item == 4)if (((CurrentDate.monthl>2) & (KeyNew == 0)) | ((CurrentDate.monthl == 0) & (KeyNew == 1))| (((CurrentDate.monthl == 1) | (CurrentDate.monthl == 2)) & (KeyNew <2))) {CurrentDate.monthh = KeyNew;lcd_write_data(CurrentDate.monthh + '0');//lcd_write_inst(time_start_addr + 5);adjust_item ++;}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 3);}else if (KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 6);}}else if(adjust_item == 5){if (((CurrentDate.monthh == 3) & (KeyNew <2)) | ((CurrentDate.monthh != 3) & (KeyNew >=0) & (KeyNew <=9))){CurrentDate.monthl = KeyNew;lcd_write_data(CurrentDate.monthl + '0');//lcd_write_inst(time_start_addr + 6);adjust_item ++;lcd_write_inst(time_start_addr + 8);}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 5);}else if (KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 8);}}else if(adjust_item == 6)if (((CurrentDate.dayl>1) & ((KeyNew == 1) | (KeyNew == 2))) | ((CurrentDate.dayl == 0) & (KeyNew >0) & (KeyNew<4))| ((CurrentDate.dayl == 1) & (KeyNew <4))){CurrentDate.dayh = KeyNew;lcd_write_data(CurrentDate.dayh + '0');//lcd_write_inst(time_start_addr + 8);adjust_item ++;}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 6);}else if (KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 9);}}else if(adjust_item == 7){if (((CurrentDate.dayh == 3) & (KeyNew <2)) | ((CurrentDate.dayh != 3) & (KeyNew >=0) & (KeyNew <=9))){CurrentDate.dayl = KeyNew;lcd_write_data(CurrentDate.dayl + '0');//lcd_write_inst(time_start_addr + 9);adjust_item ++;lcd_write_inst(time_start_addr + 0);}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 8);}else if (KeyNew == key_right){adjust_item = 0;lcd_write_inst(time_start_addr + 0);}}}// -------------------------------------------------------void set_time(void){if (adjust_item == 0) // set hourh{if (((CurrentTime.hourl <4) & (KeyNew < 3)) | ((CurrentTime.hourl >3) & (KeyNew <2))){CurrentTime.hourh = KeyNew;lcd_write_data(CurrentTime.hourh + '0'); // refresh hourh//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item = 5;lcd_write_inst(time_secondl_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_hourl_addr);}}else if (adjust_item == 1) // set hourl{if (((CurrentTime.hourh == 2) & (KeyNew < 4)) | ((CurrentTime.hourh < 2) & (KeyNew <=9))){CurrentTime.hourl = KeyNew;lcd_write_data(CurrentTime.hourl + '0'); // refresh hourl//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minuteh_addr);}}else if (adjust_item == 2) // set minuteh{if (KeyNew <6){CurrentTime.minuteh = KeyNew;lcd_write_data(CurrentTime.minuteh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourl_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minutel_addr);}}else if (adjust_item == 3) // set minutel{if ((KeyNew >=0) & (KeyNew <=9)){CurrentTime.minutel = KeyNew;lcd_write_data(CurrentTime.minutel + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondh_addr);}}else if (adjust_item == 4) // set secondh{if (KeyNew <6){CurrentTime.secondh = KeyNew;lcd_write_data(CurrentTime.secondh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;&nb, sp; lcd_write_inst(time_minutel_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr);}}else if (adjust_item == 5) // set secondl{if ((KeyNew >=0) & (KeyNew <=9)){CurrentTime.secondl = KeyNew;lcd_write_data(CurrentTime.secondl + '0');//lcd_write_inst(0x10); // move cursor backadjust_item = 0;lcd_write_inst(time_hourh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_right){adjust_item = 0;lcd_write_inst(time_hourh_addr);}}}// -------------------------------------------------------void set_alarm1(void){if (adjust_item == 0) // set hourh{if (((AlarmTime1.hourl <4) & (KeyNew < 3)) | ((AlarmTime1.hourl >3) & (KeyNew <2))){AlarmTime1.hourh = KeyNew;lcd_write_data(AlarmTime1.hourh + '0'); // refresh hourh//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item = 6;lcd_write_inst(time_secondl_addr + 3);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_hourl_addr);}}else if (adjust_item == 1) // set hourl{if (((AlarmTime1.hourh == 2) & (KeyNew < 4)) | ((AlarmTime1.hourh < 2) & (KeyNew <=9))){AlarmTime1.hourl = KeyNew;lcd_write_data(AlarmTime1.hourl + '0'); // refresh hourl//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minuteh_addr);}}else if (adjust_item == 2) // set minuteh{if (KeyNew <6){AlarmTime1.minuteh = KeyNew;lcd_write_data(AlarmTime1.minuteh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourl_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minutel_addr);}}else if (adjust_item == 3) // set minutel{if ((KeyNew >=0) & (KeyNew <=9)){AlarmTime1.minutel = KeyNew;lcd_write_data(AlarmTime1.minutel + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondh_addr);}}else if (adjust_item == 4) // set secondh{if (KeyNew <6){AlarmTime1.secondh = KeyNew;lcd_write_data(AlarmTime1.secondh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minutel_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr);}}else if (adjust_item == 5) // set secondl{if ((KeyNew >=0) & (KeyNew <=9)){AlarmTime1.secondl = KeyNew;lcd_write_data(AlarmTime1.secondl + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondl_addr+3);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr+3);}}else if (adjust_item == 6) // set on/off{if ((KeyNew == key_up) | (KeyNew == key_down)){if (Alarm1Enable){Alarm1Enable =false; // disable alarm1lcd_write_data('f');lcd_write_data('f');}else{Alarm1Enable =true; // enable alarm1lcd_write_data('n');lcd_write_data(' ');}//lcd_write_inst(time_secondl_addr+3);adjust_item = 0;lcd_write_inst(time_hourh_addr);Alarm1Cnt = 0;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondl_addr);}else if(KeyNew == key_right){adjust_item = 0;lcd_write_inst(time_hourh_addr);}}}// -------------------------------------------------------void set_alarm2(void){if (adjust_item == 0) // set hourh{if (((AlarmTime2.hourl <4) & (KeyNew < 3)) | ((AlarmTime2.hourl >3) & (KeyNew <2))){AlarmTime2.hourh = KeyNew;lcd_write_data(AlarmTime2.hourh + '0'); // refresh hourh//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item = 6;lcd_write_inst(time_secondl_addr+3);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_hourl_addr);}}else if (adjust_item == 1) // set hourl{if (((AlarmTime2.hourh == 2) & (KeyNew < 4)) | ((AlarmTime2.hourh < 2) & (KeyNew <=9))){AlarmTime2.hourl = KeyNew;lcd_write_data(AlarmTime2.hourl + '0'); // refresh hourl//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minuteh_addr);}}else if (adjust_item == 2) // set minuteh{if (KeyNew <6){AlarmTime2.minuteh = KeyNew;lcd_write_data(AlarmTime2.minuteh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourl_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minutel_addr);}}else if (adjust_item == 3) // set minutel{if ((KeyNew >=0) & (KeyNew <=9)){AlarmTime2.minutel = KeyNew;lcd_write_data(AlarmTime2.minutel + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondh_addr);}}else if (adjust_item == 4) // set secondh{if (KeyNew <6){AlarmTime2.secondh = KeyNew;lcd_write_data(AlarmTime2.secondh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minutel_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr);}}else if (adjust_item == 5) // set secondl{if ((KeyNew >=0) & (KeyNew <=9)){AlarmTime2.secondl = KeyNew;lcd_write_data(AlarmTime2.secondl + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondl_addr+3);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr+3);}}else if (adjust_item == 6) // set on/off{if ((KeyNew == key_up) | (KeyNew == key_down)){if (Alarm2Enable){Alarm2Enable =false; // disable alarm2lcd_write_data('f');lcd_write_data('f');}else{Alarm2Enable =true; // enable alarm2lcd_write_data('n');lcd_write_data(' ');}//lcd_write_inst(time_secondl_addr+3);adjust_item = 0;lcd_write_inst(time_hourh_addr);Alarm2Cnt = 0;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondl_addr);}else if(KeyNew == key_right){adjust_item = 0;lcd_write_inst(time_hourh_addr);}}}// -------------------------------------------------------void main(void){unsigned char cnt;TRISC = 0x03; // PORTC.3 drive led,low activePORTC_MAP = 0x00;led = 0;BackLightEn = 0;BackLightTimer = 0;PORTC = PORTC_MAP;TRISA = 0xff; // low half byte as keyscan inTRISE = 0x00;ADCON0 = 0x00;ADCON1 = 0x06; // all digital I/Oslcd_init();INTCON = 0x00;lcd_write_inst(0x80); // set lcd ddram addressfor (pStr = StrPower1;*pStr!=0;pStr++){lcd_write_data(*pStr);}lcd_write_inst(0x0c); // LCD cursor offPIR1 = PIR2 = 0x00;T1CON = 0x0f; // T1CON: -- T1CKPS1 T1CPS0 T1OSCEN /T1SYNC TMR1CS TMR1ONTMR1H = 0x80;TMR1L = 0x00;。

pic16f877a编程实例

pic16f877a编程实例

pic16f877a编程实例pic16f877a是一款常用的单片机,被广泛应用于嵌入式系统中。

它具有多种功能和强大的性能,可以实现各种应用需求。

本文将以pic16f877a编程实例为主题,介绍其基本特性和常见应用。

pic16f877a是一款8位单片机,采用哈佛架构,具有高性能和低功耗的特点。

它内置了8KB的程序存储器,368字节的数据存储器,以及35个I/O引脚,可以满足大多数嵌入式系统的需求。

我们来看一个简单的实例,通过pic16f877a控制LED灯的开关。

```c#include <pic16f877a.h>void main() {TRISB0 = 0; // 设置RB0为输出引脚while(1) {RB0 = 1; // 将RB0引脚电平设置为高,LED灯亮__delay_ms(1000); // 延时1秒RB0 = 0; // 将RB0引脚电平设置为低,LED灯灭__delay_ms(1000); // 延时1秒}}```在上面的程序中,我们首先将RB0引脚设置为输出引脚,然后进入一个无限循环。

在循环中,我们将RB0引脚电平设置为高,LED灯亮起,然后延时1秒;然后将RB0引脚电平设置为低,LED灯熄灭,再次延时1秒。

通过不断重复这个过程,我们可以实现LED灯的闪烁效果。

除了控制LED灯,pic16f877a还可以用来控制其他外设,如蜂鸣器、液晶显示屏等。

下面是一个使用pic16f877a控制蜂鸣器的实例。

```c#include <pic16f877a.h>void main() {TRISB0 = 0; // 设置RB0为输出引脚while(1) {RB0 = 1; // 将RB0引脚电平设置为高,蜂鸣器鸣叫__delay_ms(1000); // 延时1秒RB0 = 0; // 将RB0引脚电平设置为低,蜂鸣器停止鸣叫__delay_ms(1000); // 延时1秒}}```在上面的程序中,我们同样将RB0引脚设置为输出引脚,并进入一个无限循环。

用PIC16F877A单片机制作的PWM参数测量仪

用PIC16F877A单片机制作的PWM参数测量仪

用PIC16F877A单片机制作的PWM参数测量仪用PIC16F877A单片机制作的PWM参数测量仪一、测量原理电路如上图(电源电路略)。

外部频率信号从单片机CCP1(RC2)脚输入,测量结果显示在液晶屏上。

PIC16F877A单片机内部有2个CCP模块。

当它工作在PWM方式时。

可以产生周期和电平宽度均可由编程决定的PWM波形;当它工作在捕捉方式时。

可以捕捉外部输入脉冲的上升沿或下降沿,当输入信号发生边沿跳变时,CCP模块立即把当时TMR1的16位计数值放入CCPRxH和CCPRxL寄存器。

并产生相应的中断。

利用CCP 模块的捕捉功能,可以很容易地完成。

PWM信号的周期、频率、脉宽、占空比等参数的测量。

PWM信号参数的测量以周期测频法为基础。

原理如右图所示。

把单片机的CCP1模块设置为捕捉模式,先把CCP1设置为捕捉脉冲的上升沿。

当脉冲信号上升沿到来时。

触发CCP中断,并在中断服务程序中记录下此时TMR1寄存器中16位的值T1:然后把CCP1模块设置成捕捉脉冲下降沿,当脉冲信号下降沿到来时,再次触发CCP中断。

并在中断服务程序中记录下此时TMR1寄存器中16位的值T2;最后把CCP1模块设置成捕捉脉冲上升沿,当脉冲信号上升沿到来时,触发CCP 中断,并在中断服务程序中记录下此时TMR1寄存器中16位的值T3,这样就完成了PWM信号一个周期的测量。

示例程序如下:通过T1~T3可算出PWM信号的周期、频率、脉宽、占空比等。

当PIC16F877A使用4MHz晶振时。

时钟周期=1/4MHz=250ns,指令周期=1μs,TMR1寄存器中16位数值的单位就是μs。

PWM信号各参数的计算方法如下:信号周期:T=(T3-T1)μs;信号频率:F=1000000/T;脉冲宽度:P=(T2-T1)μs;占空比:R=P/T×100%。

为了提高准确性。

可以重复测量多个周期的PWM信号参数,以平均值为最终测量结果。

pic16f877a程序

pic16f877a程序

实验二程序清单:(1)编写程序使8个LED实现双跳灯显示//===========led程序===========#include <pic.h>//===========变量定义==========void delay(int z);//===========主程序============main(){TRISD=0x00;while(1){PORTD=0x03;delay(200);PORTD=0x0c;delay(200);PORTD=0x30;delay(200);PORTD=0xc0;delay(200);}}void delay(int z){int x,y;for(x=z;x>0;x--)for(y=120;y>0;y--);}(2)编写程序实现8个LED灯高四位和低四位交替点亮//===========led程序===========#include <pic.h>//===========变量定义==========void delay(int z);//===========主程序============main(){TRISD=0x00;while(1){PORTD=0xf0;delay(500);PORTD=0x0f;delay(500);}}void delay(int z){int x,y;for(x=z;x>0;x--)for(y=120;y>0;y--);}(3)编写程序使第一次按下按键时单双星闪(1、3、5、7个 LED灯与2、4、6、8个LED交替点亮),第二次按下按钮时高四位的LED和低四位的LED交替点亮,这两种显示方式依次循环#include <pic.h>//===========变量定义==========void delay(int z);void KEYSCAN();#define shuru RB0unsigned int i,j;//===========主程序============ main(){TRISD=0x00;TRISB=0X01;//设置RB0为输入i=0;PORTD=0XFF;while(1){KEYSCAN();if(i%2==1){PORTD=0xaa;delay(500);PORTD=0x55;delay(500);}if(i%2==0){PORTD=0xf0;delay(500);PORTD=0x0f;delay(500);}}}void delay(int z){int x,y;for(x=z;x>0;x--)for(y=120;y>0;y--);}void KEYSCAN(){while(1){if(shuru==1)break;} /*等待有键按下*/delay(10); /*软件延时*/if(shuru==1)i++; /* 如果仍有键按下,则调用键服务子程序*/}实验三程序清单:(1)4*4键盘扫描#include<pic.h> //包含单片机内部资源预定义const charLEDCODE[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7c,0x 39,0x5e,0x79,0x71};int result;void delay(); //delay函数申明void init(); //I/O口初始化函数申明void scan(); //按键扫描程序申明void display(int x); //显示函数申明//---------------------------------------------------//主程序void main(){while(1) //循环工作{init(); //调用初始化子程序scan(); //调用按键扫描子程序display(result); //调用结果显示子程序}}//---------------------------------------------------//初始化函数void init(){TRISD=0X0f; //设置C口高4位为输入,低4位为输出TRISC=0X00; //设置D口为输出PORTC=0X00;PORTD=0X00; //先清除所有显示}//按键扫描程序void scan(){PORTD=0XEF; //C3输出低电平,其他三位输出高电平asm("nop"); //插入一定延时,确保电平稳定result=PORTD; //读回C口高4位结果result=result&0x0f; //清除低4位if(result!=0x0f) //判断高4位是否为全1(全1代表没按键按下)?{result=result|0xE0; //否,加上低4位0x07,做为按键扫描的结果return;}PORTD=0XDF; //C3输出低电平,其他三位输出高电平asm("nop"); //插入一定延时,确保电平稳定result=PORTD; //读回C口高4位结果result=result&0x0f; //清除低4位if(result!=0x0f) //判断高4位是否为全1(全1代表没按键按下)?{result=result|0xD0; //否,加上低4位0x07,做为按键扫描的结果return;}PORTD=0XBF; //C3输出低电平,其他三位输出高电平asm("nop"); //插入一定延时,确保电平稳定result=PORTD; //读回C口高4位结果result=result&0x0f; //清除低4位if(result!=0x0f) //判断高4位是否为全1(全1代表没按键按下)?{result=result|0xB0; //否,加上低4位0x07,做为按键扫描的结果return;}PORTD=0X7F; //C3输出低电平,其他三位输出高电平asm("nop"); //插入一定延时,确保电平稳定result=PORTD; //读回C口高4位结果result=result&0x0f; //清除低4位if(result!=0x0f) //判断高4位是否为全1(全1代表没按键按下)?{result=result|0x70; //否,加上低4位0x07,做为按键扫描的结果return;}}//显示程序void display(int x){switch(result){case 0xee:PORTC= LEDCODE[0];delay();break; case 0xed:PORTC= LEDCODE[1];delay();break; case 0xeb:PORTC= LEDCODE[2];delay();break; case 0xe7:PORTC= LEDCODE[3];delay();break;case 0xde:PORTC= LEDCODE[4];delay();break;case 0xdd:PORTC= LEDCODE[5];delay();break; case 0xdb:PORTC= LEDCODE[6];delay();break; case 0xd7:PORTC= LEDCODE[7];delay();break;case 0xBE:PORTC= LEDCODE[8];delay();break;case 0xbd:PORTC= LEDCODE[9];delay();break; case 0xBb:PORTC= LEDCODE[10];delay();break; case 0xb7:PORTC= LEDCODE[11];delay();break; case 0x7E:PORTC= LEDCODE[12];delay();break; case 0x7d:PORTC= LEDCODE[13];delay();break; case 0x7b:PORTC= LEDCODE[14];delay();break;case 0x77:PORTC= LEDCODE[15];delay();break;}}//延时程序void delay() //延时程序{int i; //定义整形变量for(i=0x100;i--;); //延时}(2)数码管显示#include<pic.h> //包含单片机内部资源预定义// __CONFIG(0x1832);//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡void delay(); //delay函数申明void init(); //I/O口初始化函数申明char TABLE[]={0,1,2,3,4}; //定义常数0-5的数据表格const charLEDCODE1[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};//共阴码void main(){init(); //调用初始化函数while(1) //死循环,让数码管持续{PORTC=0X01; //点亮第1位数码管PORTD=~LEDCODE1[TABLE[0]]; //D口输出数据表格第1个数据0 delay();PORTD=0xFF; //延时一定时间,保证数码管亮度PORTC= 0x02;PORTD=~LEDCODE1[TABLE[1]]; //显示数据1delay();PORTD=0xFF;PORTC= 0x04;PORTD=~LEDCODE1[TABLE[2]]; //显示数据2delay();PORTD=0xFF;PORTC= 0x08;PORTD=~LEDCODE1[TABLE[3]]; //显示数据3delay();PORTD=0xFF;}}void init() //I/O口初始化函数{TRISC=0X00; //设置A0输出,其他输入TRISD=0X00; //设置D口输出PORTC=0x00;PORTD=0x00; //先熄灭所有显示}void delay() //延时程序{int i; //定义整形变量for(i=0xF000;i--;); //延时 //0x400for(i=0xff;i--;);}void display(){int i ;unsigned char DISPBIT;DISPBIT=0x01;for (i=0;i<=3;i++){PORTC=DISPBIT; //点亮第1位数码管PORTD=~LEDCODE1[TABLE[i]]; //D口输出数据表格第1个数据0 delay();PORTD=0xFF;DISPBIT=DISPBIT<<1;}}实验四程序清单:(1)方波发生器#include<pic.h>sbit P1_0=P1^0;void timer0(void){P1_0=!P1_0;TH0=-(1000/256); /*计数初值重装*/TL0=-(1000%256);}void main(void){TMOD=0x01; /*T0工作在定时器方式1*/P1_0=0;TH0=-(1000/256); /*预置计数初值*/TL0=-(1000%256);EA=1; /*CPU开中断*/ET0=1; /*T0开中断*/TR0=1; /*启动T0*/do{}while(1);}(2)程序说明:P1口输出,低电平有效#include<pic.h>#define uchar unsigned char //定义无符号字符#define uint unsigned int //定义无符号整数void Delayms(uint x){ //定义延时函数uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void main(){uint i;uchar temp;while(1){temp=0x01; //8个流水灯逐个闪动for(i=0;i<8;i++){P1=~temp;Delayms(300);temp<<=1;}temp=0x80; //8个流水灯反向逐个闪动for(i=0;i<8;i++){P1=~temp;Delayms(300);temp>>=1;}temp=0xfe; //8个流水灯依次全部点亮for(i=0;i<8;i++){P1=temp;Delayms(300);temp<<=1;}temp=0x7f; //8个流水灯依次反向全部点亮for(i=0;i<8;i++){P1=temp;Delayms(300);temp>>=1;}}}实验六程序清单:(1) U1发送部分程序清单#include<pic.h>unsigned tran[10]={0,2,4,6,8,1,3,5,7,9};unsigned char k,x;int i=0;const chartable[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xD8,0x80,0x90,0x88,0x83,0x c6,0xa1,0x86,0x8c,0x7f,0xbf,0x89,0xff};void sciint(){SPBRG=0x19;TXSTA=0x04;RCSTA=0x80;TRISC6=1;TRISC7=1;TRISB=0x00;}void delay(){for(i=0x1FFF;i>0;i--) {;}}void display(){for(k=0;k<10;k++) { x=tran[k];PORTB=table[x];delay();}}main(){sciint();di();TXEN=1;CREN=1;for(k=0;k<10;k++){ TXREG=k;while(1){if(TXIF==1)break;}while(1){if(RCIF==1)break;}RCREG=RCREG;}display();while(1){;}}(2) U2接收部分程序清单#include<pic.h>unsigned rece[10];unsigned char k,x;int i=0;const chartable[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xD8,0x80,0x90,0x88,0x83,0x c6,0xa1,0x86,0x8c,0x7f,0xbf,0x89,0xff};void sciint(){SPBRG=0x19;TXSTA=0x04;RCSTA=0x80;TRISC6=1;TRISC7=1;TRISB=0x00;}void delay(){for(i=0x1FFF;i>0;i--){;}}void display(){for(k=0;k<10;k++) { x=rece[k];PORTB=table[x]; delay();}}main(){sciint();di();CREN=1;TXEN=1;for(k=0;k<10;k++){ while(1){if(RCIF==1)break;}rece[k]=RCREG; TXREG=rece[k];while(1){if(TXIF==1)break;}}display();while(1){;}}实验七程序清单:(1)单路显示#include<pic.h>unsigned int i;unsigned int a,b,c;static inttable[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xD8,0x80,0x90,0x88,0x83,0x c6,0xa1,0x86,0x8c,0x7f,0xbf,0x89,0xff};void initial() //初始化{TRISB=0x00; //定义为输出PORTB=0x13; //数码管全灭TRISC=0x00;PORTC=0x13;a=0;b=0;c=0;}void ADC() //A/D转换初始化{ADCON0=0x41; //0100 0001 选择转换时钟8Tosc,选择A/D通道为RA0,//打开A/D转换器。

PIC16F877A数字时钟时钟程序(优推内容)

PIC16F877A数字时钟时钟程序(优推内容)

;Digit clock;-----------------------------------------------;DA TE :20101205;Author:Tang HS;M C U :PIC16F877A;FileName : ClockPIC.ASM;-----------------------------------------------------------;Date: {2010/12/07.14:35}-V er01--CS-ICD:0xAFCE---ISP:0xb7ce----;功能: 1.LED显示:时分秒;格式:[ hh mm ss ] 备注:按键未定义;------------------------------------------------------------;-----------------------------------------------------------;Date: {2010/12/07.22:15}-V er01--CS-ICD:0xAFCE---ISP:0xb7ce----;功能: 1.LED显示:时分秒;格式:[ hh mm ss ] 备注:按键未定义; 2.RB0-SET_KEY;RB1-ADD_KEY;RB2-SUB_KEY;RB3-EXIT_KEY;------------------------------------------------------------;Date: {2010/12/09.18:06}-V er02--CS-ICD:0xAFCE---ISP:0xef0e----;************************************************************;Date: {2010/12/10.00:47}-V er03--CS-ICD:0xb08d---ISP:0xfaa7----;功能: 1.LED显示:时分秒;格式:[ hh mm ss ] 备注:按键未定义; 2.RB0-SET_KEY;RB1-ADD_KEY;RB2-SUB_KEY;RB3-EXIT_KEY 都OK ; 3.MOVLW 纠正MOVV REG,1 引起的SUB_不良;;--------------------------------------------------------------;Date: {2010/12/10.13:10}-V er03.1--CS-ICD:0xb08b---ISP:0xfaa4----; 4.时差。

PIC16F877A单片机中文文献

PIC16F877A单片机中文文献

PIC16F877A单片机是microchip公司的产品,它采用14位的RISC指令系统,内部集成了A/D转换器、EEPROM、模拟比较器、带比较和捕捉功能的定时器/计数器、PWM输出、异步串行通信电路等。

1.程序存储器程序存储器和堆栈PIC16F877A单片机内部具有8K×14位的Flash程序存储器,程序存储器具有13位宽度的程序计数器地址范围:0000H-1FFFH。

由程序计数器提供13条地址线进行单元选择,每个单元宽14位,即PIC16F877A的指令字节宽度为14位,能够存放一条PIC单片机系统指令。

在系统上电或其他复位情况下,程序计数器均从0000H地址单元开始工作。

如果遇到调用子程序或系统发生事件中断时,将把当前程序断点处的地址送入8级×14位的堆栈区域进行保护。

堆栈是一个独立的存储区域,在调用的子程序或中断服务程序执行完后,再恢复断点地址。

通过14位程序总线,取出对应程序之灵的机器码,送入指令存储器,将组成的操作码和操作数进行有效分离。

如果操作数为地址,则进入地址复用器;如果操作数为数据,则进入数据复用器。

而操作码将在指令译码和控制单元中转化为相应的功能操作。

PIC的多数指令均是顺序执行,即使条件跳转也是隔行间接跳转。

具有大范围转移功能的指令只有两条:无条件GOTO语句和调用子程序CALL语句。

但它们受到2KB范围的约束。

所以必须将整个程序存储器以2KB为单位进行分页。

PIC16F877A单片机的上电复位地址是0000H,中端口地址是0004H,中断产生时PC指针会自动指向该地址。

在进行中断应用时,特别是涉及多个中断同时打开时,必须要逐个对中断标志进行判断。

编程时,在0000H-0003H单元内要放置一条GOTO跳转指令,跳转到主程序,以避开0004H存储器单元。

2.数据存储器数据存储器PIC单片机的数据存储器与传统的MCS-51单片机一样,在配置结构上可分为通用寄存器和特殊功能寄存器两大类。

基于PIC16F877A时钟程序实验C程序

基于PIC16F877A时钟程序实验C程序
PORTB=0x00;
TMR1CS=0;
T1CKPS1=1;
T1CKPS0=1;
TMR1H=0x0B;
TMR1L=0xE9;
T1SYNC=0Βιβλιοθήκη TMR1ON=1; TMR1IF=0;
TMR1IE=1;
PEIE=1;
GIE=1;
while(1)
U5C=0; //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
PORTD=LED[j%10];
}
}
}
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《
{
U5A=0; //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
U5B=1; //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
U5C=0; //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
PORTD=0x00;
PORTB=0x00;
TMR1CS=0;
T1CKPS1=1;
T1CKPS0=1;
TMR1H=0x0B;
TMR1L=0xE9;
T1SYNC=0;
TMR1ON=1;
TMR1IF=0;
TMR1IE=1;
PEIE=1;
GIE=1;
while(1)
{
PORTD=0x00; //关一次显示,以免显示出鬼影
if(j>59)j=0;
if(++d>3) d=1;
if(d==2) //如果d=2,显示十位

PIC16F877A时钟程序

PIC16F877A时钟程序
STRSET2 EQU 37H
STRSET3 EQU 38H
STRSET4 EQU 39H
ALARMMARK EQU 3AH
ALARM_MM1 EQU 3BH
ALARM_MM2 EQU 3CH
NOP
NOP
NOP
DECFSZ TIME500MS2,1
GOTO T500_LOOP2
DECFSZ TIME500MS1
GOTO T500_LOOP1
RETURN
END
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
RETLW 0X4F ;3
RETLW 0X66 ;4
RETLW 0X6D ;5
RETLW 0X7D ;6
RETLW 0X07 ;7
RETLW 0X7F ;8
RETLW 0X6F ;9
RETLW 0X3F ;0
SUBLW 0X4F
BTFSC STATUS,2
GOTO CLRFDD2
MOVF DATECOUNT3,0

(完整word版)基于PIC16F877A的数字钟设计

(完整word版)基于PIC16F877A的数字钟设计

电子工程系项目考核(报告)项目名称:数字时钟项目姓名班级学号课程名称一、项目要求:数码管默认显示00:00。

数码管1,2 表示小时,数码管3,4 表示分钟。

如此,实现时钟功能.要求能够整点报时、闹钟提示;并附带有秒表功能。

按键可以调整时钟时间、切换显示页面和设定闹钟时间等。

二、项目原理分析在项目用的单片机开发板上单片机的IO 口接四位数码管的各段。

同时开发板共阴数码管的阴极由138 译码器的输出端控制。

在该项目中我采用了数码管的动态显示,即每位数码管点亮2ms 时间左右,由于人的视觉暂留现象及发光二极管的余辉效应,只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O 端口,而且功耗更低。

在实现了数码管的动态显示的基础上在主程序中通过计算定时器1的中断次数,从而得到计时时间和秒表时间的基准时间。

同时在主程序中添加按键处理程序,实现时钟的开始、中断和校时,同时实现闹钟定时和切换显示等功能,还有秒表计时功能。

三、硬件电路图以及原理3。

1 硬件电路图如下:3。

2硬件原理:该项目中,主要的功能模块有:数码管显示模块;按键模块;蜂鸣器模块。

数码管显示模块主要是由芯片PIC16F877A内部的定时器1的定时中断实现数码管的动态显示.按键模块主要利用矩阵式按键实现多按键功能,矩阵式按键原理是在一端加高电平,然后检测另一端是否为高电平来判断按键是否按下,通过不同的定义可以让按键实现不同的功能。

蜂鸣器模块通过三极管的开关作用和驱动作用由芯片控鸣叫与否。

四、程序说明以及程序流程图该时钟默认显示页面为时钟计时页面,按键SW1 控制时钟、秒表的开始和中断,按按键SW1一次,如果数码管在显示秒表,则开始计秒功能;否则,开始正常计时;再按一次SW1则实现中断功能.按键SW2实现是数码管的选位,从第一个数码管开始,按一次就选中下一位数码管,循环选择。

SW3实现的是加1功能,每按一次就在SW2选中的位上加1。

毕业设计-基于PIC16F877A单片机字符液晶显示数字时钟设计

毕业设计-基于PIC16F877A单片机字符液晶显示数字时钟设计

贵港职业学院毕业设计(论文)姓名:覃正杨学号:200930112126专业班级:电机系09级应用电子技术班论文题目:基于PIC16F877A字符液晶数字时钟指导教师:------二零一一年六月基于PIC16F877A单片机字符液晶显示数字时钟摘要近年来,随着电子产品的发展,人们对数字钟的要求越来越高,针对人们的这一需求设计了一种有单片机控制的智能化数字时钟,功能强大,界面友好,更好的满足了人们对它的智能化要求。

本文设计并实现了一款基于字符液晶显示的单片机数字钟,详细叙述了系统硬件、软件的具体实现过程。

论文重点阐述了数字钟硬件模块、时钟模块和相关控制模块等的模块化设计与制作;软件同样采用模块化的设计,包括读取模块、显示模块、时间调整模块设计,并采用汇编言语编写实现。

本设计实现了年、月、日和时间的显示功能、日期和时间修改功能。

设计方案已通过仿真软件验证,证明了设计的合理性。

关键词:单片机;数字钟;液晶显示;仿真目录目录 (3)引言 (4)第一章方案对比与选择 (5)方案1 (5)方案2 (5)方案选择 (5)第二章16F877A单片机概述 (6)2.1 单片机的用途与发展 (6)2.2 PIC16F877A单片机的结构与特点 (6)2.2.1 PIC16F877A单片机引脚结构 (6)2.2.2 PIC16F877A的内部结构 (7)2.2.3单片机的特点 (7)本章小结 (8)第三章LCD 1602A字符液晶显示说明 (9)3.1 LCD 1602A字符液晶显示的优势 (9)3.2 LCD 1602A字符液晶引脚说明 (9)本章小结 (9)第四章整体设计方案 (10)4.1 硬件选择 (10)4.3 PIC16F877A单片机电路 (10)4.4 LCD 1602A字符液晶显电路 (11)4.5 电源电路 (11)4.6 轻触按键电路 (11)4.7 整体电路图 (12)4.8 程序主流程图 (12)4.9 LCD 1602A字符液晶程序流程图 (13)本章小结 (13)第五章在线调式 (14)5.1 MPLAB ICD 2 在线调试器 (14)5.2 使用ICD 2 进行调试 (14)5.4 ICD2在线调式结果 (15)本章小结 (15)第六章结束语 (16)参考文献 (17)致谢 (17)附录字符液晶数字时钟程序 (18)引言现在是一个知识爆炸的新时代。

剖析PIC16F877型单片机TMR1的RTC功能

剖析PIC16F877型单片机TMR1的RTC功能

剖析PIC16F877型单片机TMR1的RTC功能温舒;沈跃【摘要】PIC16F87X系列单片机是美国微芯科技(Microchip Technology)公司于1998年底推出的特色产品,是目前世界上片内集成外围模块最多、功能最强、最受用户欢迎的单片机品种之一。

该系列单片机采用哈佛总线结构、高性能精简指令(RISC)、低功耗CMOS工艺,【期刊名称】《电子世界》【年(卷),期】2009(000)001【总页数】1页(P45)【关键词】PIC16F877;单片机;RTC;PIC16F87X;CMOS工艺;特色产品;总线结构;精简指令【作者】温舒;沈跃【作者单位】无【正文语种】中文【中图分类】工业技术·工程师笔记剖析 PIC16F877型单凫相 TMR1的RTC功胄苣 PIC16F87X系列单片机是美国微芯科技( MicrochipTechnology )公司于 1998年底推出的特色产品,是目前世界上片内集成外围模块最多、功能最强、最受用户欢迎的单片机品种之一。

该系列单片机采用哈佛总线结构、高性能精简指令( RISC)、低功耗 CMOS 工艺,内置 8kx 14位 FLASH、 512 字节 RAM 、256 × 8 位E2PROM,并且拥有丰富的双向 I/O 口、3个多功能定时器/计数器模块、8 路 10 位精度的~D 转换器模块、2 个输入捕捉/输出比较/脉宽调制 CCP 模块及串并口模块。

另外,还专门配备了良好的应用开发平台“ MPLAB-IDE ”,可以实现“在线调试、在线编程” 功能。

在 PIC16F87X 系列单片机中,PIC16F877 型是功能最全,且应用最广泛的型号。

PIC16F877 型单片机内置 3 个定时器/计数器模块 TMRO 、TMR1 和 TMR2 。

它们的结构不同,设计的初衷也不同,除了均能实现基本的定时/计数方式外,还各自具有专属功能。

本文就 TMR1 定时器特有的实时时钟 RTC(RealTimeClock) 功能进行简单介绍,并对在编程时的注意事项加以说明。

PIC16F87X单片机的定时器-计数器的应用

PIC16F87X单片机的定时器-计数器的应用

PIC16F87X 单片机的定时器/计数器的应用
PIC16F87X 单片机内部配置了3 个定时器/计数器,分别记为TMR0、TMR1、TMR2。

这3 个定时器/计数器模块不仅在电路结构上不相同,而且其在设计的初衷和使用上也各有不同。

·定时器/计数器TMR0。

定时器/计数器TMR0 是3 个同类模块中最常用的器件,与定时器/计数器TMR0 相关的寄存器共有4 个,分别为累加计数寄存器TMR0、选项寄存器OPTION REG、中断控制寄存器INTCON 和端口RA 方向寄存器TRISA。

·定时器/计数器TMR1。

定时器/计数器TMR1 是一个由两个8 位可读写的寄存器(TMR01H 和TMRIL)组成的16 位定时器/计数器,它带有一个3 位的可编程预分频器和一个内置的低功耗低频时基振荡器。

基于PIC16F887单片机的温度、时钟显示以及闹钟功能

基于PIC16F887单片机的温度、时钟显示以及闹钟功能

基于PIC16F887单片机的温度、时钟显示以及闹钟功能一、课程设计的目的《PIC 单片机课程设计》是电气工程及其自动化专业及相近专业的一门重要的专业实践课,本课程在《PIC 单片机》课程的基础上,通过硬件设计与软件编程与调试的实践,进一步掌握PIC 单片机的应用方法,熟练PIC 单片机的C 程序的编写与调试,是毕业设计前的一次重要的实践,为今后走上工作岗位打下坚实的单片机应用基础。

二、设计内容1 Proteus 线路图绘制根据所设计的线路图,绘制与之一致的,能用于仿真的Proteus 线路图。

要求所绘的线路图美观、紧凑,参数要与课设一致。

2、软件编制与调试根据所设计的线路图制相应的单片机C 程序,要求所制的程序符合C 语言格式并加上注解。

每编一段即进行译,有错及时修改,并先在Proteus 上仿真,基本正确后再用PICkit3 在线调试,最后应脱机运行。

三、设计目标1该设计包括数字钟及数字温度计:按键的使用.LCD.蜂鸣器时钟芯片DS1307和温度传感器TC74。

2功能;此设计可以感测环境的温度,显示当前的时间,及闹钟。

温度与时间都显示在LCD显示屏上,以及如何调整闹钟界面四硬件设计及说明1复位按键2时钟芯片DS1307及附属接线时钟芯片DS1307用于产生时间,它提供了秒、分、时、日、年、和星期等数据,能算只瑞年2100年,时钟的晶振是典型的32.768Hz。

(1)其引脚作用如下:2(2)DS1307的读写如下;1写DS1307 的步骤如下:a) 发送启始位;b) 发送DS1307 的7位地址+0 (写),即0b11010000;c) 发送要写入DS1307 的地址,地址见图16,如要修改分,此值为1;d) 发送要写入DS1307 的数,如要把分修改为十进制数37,则此数为0x37;e) 发送停止位;2读DS1307 的步骤如下:a) 发送启始位;b) 发送DS1307 的7位地址+0 (写),即0b11010000;c) 发送要读的DS1307 的起始地址,如要从秒读起,为0;d) 发送停止位;e) 发送重新开始位;f) 发送DS1307 的7位地址+1 (读),即0b11010001;g) 发送读使能位,接收一个数据,单片机发送应答位;h) 发送读使能,接收下一个数据(地址会自动+1),单片机发送应答位,直到读数完成,接收最后一个数时单片机不发送应答位;i) 发送停止位;注意在DS1307仿真的时候七位地址为0b1001101 而实际为0b1001000 ;(3)功能是;提供时间通过pic16F877送入LCD中显示。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

PIC16F877A TIMER1计数操作
/**********************
Title:PIC16F877A TIMER1计数操作
Author:hnrain
Date:2010-12-28
使用前置分频器
T1CKPS1 T1CKPS1
0 0 1 分频TMR1时钟为晶振时钟/(4*1)
0 1 2 分频TMR1时钟为晶振时钟/(4*2)
1 0 4 分频TMR1时钟为晶振时钟/(4*4)
1 1 8 分频TMR1时钟为晶振时钟/(4*8)
TMR1是16位宽度的TMR1由2个8位的可读写的寄存器TMR1H和TMR1L组成。

TMR1有专门的启停控制位TMR1ON,通过软件可以任意启动或暂停TMR1计数功能。

T1CON:TIMER1 CONTROL REGISTER
bit7-6 unimplemented :Read as ‘0’
bit5-4 T1CKPS1:T1CKPS0:Timer1 input Clock Prescale Select bits 11=1:8 prescale value
10=1:4 prescale value
01=1:2 prescale value
00=1:1 prescale value
bit3 T1OSCEN:Timer1 Oscillator Enable Control bit
1 = Oscillator is enable
0 = Oscillator is shut-off
bit2 T1SYNC:Timer1 External Clock Input Synchronization Control bit when TMR1CS = 1
1= Do not synchronize external clock input
0= Synchronize external clock input
when TMR1CS = 0
This bit is ignored .Timer1 uses the internal clock when TMR1CS = 0. bit1 TMR1CS:Timer1 Clock Source Select bit
1 = External clock from pin RC0/T1OSO/T1CKI
0 = Internal clock
bit0 TMR1ON:Timer1 on bit
1 = enables timer1
0 = stops timer1
说明:作用在TMR1的计数状态,计数信号从RC0/T1CKI输入,
当来一个上升沿时,采集到一个有效的信号,计数到TMR1L,TMR1H中。

当计满时就会产生中断信号。

***********************/
#include <pic.h>
#include "../head/config.h"
__CONFIG(HS&WDTDIS&LVPDIS&PWRTEN);
void main(void)
{
T1CKPS0 = 0;
T1CKPS1 = 0;//不分频
TMR1L = (65536 - 1)%256;//TMR1L,TMR1H赋初值TMR1H = (65536 - 1)/256;
T1SYNC = 1;//TMR1异步计数器
TMR1CS = 1;
GIE = 1;//打开全局中断
PEIE = 1;//打开外部中断
TMR1IE = 1;//TMR1中断打开
TMR1ON = 1;
PORTD = 0x00;
TRISD = 0x00;
while(1){}
}
void interrupt ISR(void)
{
TMR1L = (65536 - 1)%256;//重新赋值
TMR1H = (65536 - 1)/256;
if(TMR1IE && TMR1IF)
{
TMR1IF = 0;
PORTD = ~PORTD;
}
}。

相关文档
最新文档