PIC16F877A开发学习板用户手册
- 格式:pdf
- 大小:1.43 MB
- 文档页数:26
PIC16F877A矩阵键盘的用法Post By:2010-9-27 13:39:00/*********************************************************************** ********Platform: PIC1687AProject : 实验16:矩阵式按键Clock F : 外部4MSoftware: PICCAuthor : 竹林清风comments:学习使用矩阵式按键的用法本例功能是按一下相应键,数码管显示相应的值0-9;不带连发,不带组合,希望有兴趣的人帮忙完成并共享UP键按键计数proteus仿真通过;************************************************************************ *******/#include <pic.h>#include <pic1687x.h>#include"delay.h"#include"key.h"unsigned char led_7[]={0x3f,0x06,0x5b,0x4F,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管显示值unsigned char key_temp;void main(void){unsigned char ID=0;TRISB=0X00;//所有B0端口输出PORTB=0XFF;TRISD=0X0F;//初始化键盘接口PORTD=0XFF;//置输出为高电平while(1){delay_nms(5);key_temp = read_keyboard(); // 调用键盘接口函数读键盘 if (key_temp != No_key){ // 有按键按下switch(key_temp){case 1:PORTB=led_7[1];break;case 2:PORTB=led_7[2];break;case 3:PORTB=led_7[3];break;case 4:PORTB=led_7[4];break;case 5:PORTB=led_7[5];break;case 6:PORTB=led_7[6];break;case 7:PORTB=led_7[7];break;case 8:PORTB=led_7[8];break;case 9:PORTB=led_7[9];break;case K3_2:PORTB=led_7[0];break;case 13:if(++ID>=10){ID=0;}PORTB=led_7[ID];break;}}}}下面为延时函数:文件delay.cvoid delay_1us(void) //1us {asm("nop");}void delay_nus(unsigned int n) //N us延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1us();}void delay_1ms(void) //1ms延时函数{unsigned int i;for (i=0;i<1140;i++);}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1ms();}头文件:delay.hvoid delay_1us(void);void delay_nus(unsigned int n); //N us延时函数void delay_1ms(void); //1ms延时函数void delay_nms(unsigned int n); //N ms延时函数键盘key.h#define No_key 255#define K1_1 1#define K1_2 2#define K1_3 3#define k1_4 4#define K2_1 5#define K2_2 6#define K2_3 7#define K2_4 8#define K3_1 9#define K3_2 0#define K3_3 10#define K3_4 11#define K4_1 12#define K4_2 13#define K4_3 14#define K4_4 15#define Key_mask 0b00001111unsigned char read_keyboard(){static unsigned char key_state = 0, key_value, key_line;unsigned char key_return = No_key,i,key_time;switch (key_state){case 0:key_line = 0b00010000;for (i=1; i<=4; i++) // 扫描键盘{PORTD = ~key_line; // 输出行线电平PORTD = ~key_line; // 必须送2次!!!key_value = Key_mask & PORTD; // 读列电平if (key_value == Key_mask)key_line <<= 1; // 没有按键,继续扫描else{key_state++; // 有按键,停止扫描break; // 转消抖确认状态}}break;case 1:if (key_value == (Key_mask & PORTD)) // 再次读列电平, {switch (key_line | key_value) // 与状态0的相同,确认按键 { // 键盘编码,返回编码值case 0b00011110:key_return = K1_1; //"1"key_state++;break;case 0b00011101:key_return = K1_2; //"2"key_state++;break;case 0b00011011:key_return = K1_3; //"3"key_state++;break;case 0b00010111:key_return = k1_4; //"4" key_state++;break;case 0b00101110:key_return = K2_1; //"5" key_state++;break;case 0b00101101:key_return = K2_2; //"6" key_state++;break;case 0b00101011:key_return = K2_3; //"7" key_state++;break;case 0b00100111:key_return = K2_4; //"8" key_state++;break;case 0b01001110:key_return = K3_1; //"9" key_state++;break;case 0b01001101:key_return = K3_2; //"0" key_state++;break;case 0b01001011:key_return = K3_3; //"A"key_state++;break;case 0b01000111:key_return = K3_4; //"B"key_state++;break;case 0b10001110:key_return = K4_1; //"C"key_state++;break;case 0b10001101://key_return = K4_2; //"D"// key_state++;key_time=0;key_state=3;break;case 0b10001011:key_return = K4_3; //"E"key_state++;break;case 0b10000111:key_return = K4_4; //"F"key_state++;break;}// 转入等待按键释放状态}elsekey_state--; // 两次列电平不同返回状态0,(消抖处理)break;case 2: // 等待按键释放状态PORTD = 0b00000111; // 行线全部输出低电平 PORTD = 0b00000111; // 重复送一次if ( (Key_mask & PORTD) == Key_mask)key_state=0; // 列线全部为高电平返回状态0 break;case 3:PORTD = 0b00000111; // 行线全部输出低电平 PORTD = 0b00000111; // 重复送一次if ( (Key_mask & PORTD) == Key_mask){key_state=0; // 列线全部为高电平返回状态0 key_return = K4_2;}//break;else if( (Key_mask & PORTD)!=Key_mask) {if(++key_time>=100){key_state=4;key_time=0;key_return=20;}}break;case 4:PORTD = 0b00000111; // 行线全部输出低电平PORTD = 0b00000111; // 重复送一次if ( (Key_mask & PORTD) == Key_mask){key_state=0; // 列线全部为高电平返回状态0 //key_return = K4_2;}else if(++key_time>=20){key_time=0;key_return=20;}break;}return key_return;}此主题相关图片如下ju.jpg:。
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:感谢大家的阅读,本文由我司收集整编。
模板的发布编制卢继珍审核批准发布日期实施日期模板更改记录模板详细内容见后文。
MPLAB X IDE快速操作指南编制卢继珍审核批准发布日期实施日期MPLAB X IDE 快速指南一、环境搭建PIC单片机的开发环境以前主要是MPLAB IDE,但由于其已经暴露出诸多问题,在2010年8月,微芯公司发布了全新的MPLAB X IDE开发环境。
见图1.1。
MPLAB® X IDE是可以运行在PC(Windows®、Mac OS®和Linux®)上的软件程序,用于开发Microchip单片机和数字信号控制器的应用。
由于它提供了一个统一的集成“环境”来支持嵌入式单片机的代码开发,因此称为集成开发环境(IDE)。
下载路径:/pagehandler/zh-cn/family/mplabx/图1.1 MPLAB X IDE集成开发环境图标由于其主要是一个集成的软件编辑环境,并不提供编译功能,所以安装MPLAB X IDE以后,我们还要安装编译器。
Microchip最新编译器产品线——MPLAB® XC为项目开发的软件需求提供完整的解决方案,并且可以替换所有MPLAB C和HI-TECH编译器。
MPLAB XC编译器具有以下特性:支持所有8/16/32位PIC® MCU以及dsPIC® DSC与MPLAB X IDE配合工作,提供全面的图形前端:•编辑错误和断点,以匹配源代码中相应的行•支持C和C++源代码单步执行,以检测关键点的变量和结构•在观察窗口显示已定义数据类型的数据结构(包括浮点)可以在Windows、Linux和Mac OS X系统上运行提供不同优化等级以满足各种需求,并且可以免费下载表1.1:Microchip PIC单片机与编译器对应表专业版标准版免费版**C++PIC10/12/16/18MCUMPLAB®XC 8MPLABXC 8MPLABXC 8MPLAB XC8 不可用PIC24 MCU和dsPIC® DSCMPLAB MPLAB MPLAB MPLAB XCMPLAB XC8编译器提供了三种模式:免费(Free)、标准(Standard)、专业(PRO)。
PIC16f877中文资料PIC16F877原理简介1.1 PIC16F877特性:PIC16F877是由Microchip公司所生产开发的新产品,属于PICmicro系列单片微机,具有Flash program程序内存功能,可以重复烧录程序,适合教学、开发新产品等用途;而其内建ICD(In Circuit Debug)功能,可以让使用者直接在单片机电路或产品上,进行如暂停微处理器执行、观看缓存器内容等,让使用者能快速地进行程序除错与开发。
如图1为PIC16F877的40根接脚图,PDIP是指一般最常见的DIP(Dual In Line Package)包装,而PIC单片机也有PLCC(Plastic Leaded Chip Carrier)与QFP(Quad Flat Package)两种形式的包装,依照不同的需求,寻找不同的包装形式。
如图所示,每根接脚都有其特定功能,例如Pin11与Pin32(VDD)为正电源接脚,Pin12与Pin31(VSS)为地线接脚;而有些接脚有两种甚至三种以上功能,例如Pin2(RA0/AN0)代表PORTA的第一支接脚,在系统重置(Reset)后,可自动成为模拟输入接脚,接收模拟讯号,也可经由程序规划为数字输出输入接脚。
图1. PDIP40引脚PIC16F877接脚说明图2. PDIP28和SOIC28引脚PIC16F877接脚图说明图3. PLCC44引脚PIC16F877脚位图说明图4. QFP44引脚PIC16F877引脚图说明PIC16F877属于闪控式(Flash)单片机,可以重复烧录,其ROM 的容量总共是8K words,以2K为一个page,区分为4个pages;内部RAM总共有512个字节(00f~1FFh),以128个字节为一个Bank,共区分为4个Bank,如图5所示,每个Bank的前半段都有其特殊用途,分别连接到其特殊功能模块,例如I/O、CCP、Timer、USART、MSSP等。
PIC16F87XAREGISTER 14-1:CONFIGURATION WORD (ADDRESS 2007h)(1)R/P-1U-0R/P-1R/P-1R/P-1R/P-1R/P-1R/P-1U-0U-0R/P-1R/P-1R/P-1R/P-1 CP—DEBUG WRT1WRT0CPD LVP BOREN——PWRTEN WDTEN F OSC1F OSC0 bit 13bit0bit 13CP: Flash Program Memory Code Protection bit1 = Code protection off0 = All program memory code-protectedbit 12Unimplemented: Read as ‘1’bit 11DEBUG: In-Circuit Debugger Mode bit1 = In-Circuit Debugger disabled, RB6 and RB7 are general purpose I/O pins0 = In-Circuit Debugger enabled, RB6 and RB7 are dedicated to the debuggerbit 10-9WRT1:WRT0 Flash Program Memory Write Enable bitsFor PIC16F876A/877A:11 = Write protection off; all program memory may be written to by EECON control10 = 0000h to 00FFh write-protected; 0100h to 1FFFh may be written to by EECON control01 = 0000h to 07FFh write-protected; 0800h to 1FFFh may be written to by EECON control00 = 0000h to 0FFFh write-protected; 1000h to 1FFFh may be written to by EECON controlFor PIC16F873A/874A:11 = Write protection off; all program memory may be written to by EECON control10 = 0000h to 00FFh write-protected; 0100h to 0FFFh may be written to by EECON control01 = 0000h to 03FFh write-protected; 0400h to 0FFFh may be written to by EECON control00 = 0000h to 07FFh write-protected; 0800h to 0FFFh may be written to by EECON controlbit 8CPD: Data EEPROM Memory Code Protection bit1 = Data EEPROM code protection off0 = Data EEPROM code-protectedbit 7LVP: Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit1 = RB3/PGM pin has PGM function; low-voltage programming enabled0 = RB3 is digital I/O, HV on MCLR must be used for programmingbit 6BOREN: Brown-out Reset Enable bit1 = BOR enabled0 = BOR disabledbit 5-4Unimplemented: Read as ‘1’bit 3PWRTEN: Power-up Timer Enable bit1 = PWRT disabled0 = PWRT enabledbit 2WDTEN: Watchdog Timer Enable bit1 = WDT enabled0 = WDT disabledbit 1-0F OSC1:F OSC0: Oscillator Selection bits11 = RC oscillator10 = HS oscillator01 = XT oscillator00 = LP oscillatorLegend:R = Readable bit P = Programmable bit U = Unimplemented bit, read as ‘0’- n = Value when device is unprogrammed u = Unchanged from programmed stateNote1:The erased (unprogrammed) value of the Configuration Word is 3FFFh.DS39582B-page 144 2003 Microchip Technology Inc.2003 Microchip Technology Inc.DS39582B-page 145PIC16F87XA14.2Oscillator Configurations14.2.1OSCILLATOR TYPESThe PIC16F87XA can be operated in four different oscillator modes. The user can program two configura-tion bits (F OSC 1 and F OSC 0) to select one of these four modes:•LP Low-Power Crystal •XT Crystal/Resonator•HS High-Speed Crystal/Resonator •RCResistor/Capacitor14.2.2CRYSTAL OSCILLATOR/CERAMIC RESONATORSIn XT, LP or HS modes, a crystal or ceramic resonator is connected to the OSC1/CLKI and OSC2/CLKO pins to establish oscillation (Figure 14-1). The PIC16F87XA oscillator design requires the use of a parallel cut crys-tal. Use of a series cut crystal may give a frequency out of the crystal manufacturer’s specifications. When in XT, LP or HS modes, the device can have an external clock source to drive the OSC1/CLKI pin (Figure 14-2).FIGURE 14-1:CRYSTAL/CERAMICRESONATOR OPERATION (HS, XT OR LPOSC CONFIGURATION)FIGURE 14-2:EXTERNAL CLOCK INPUT OPERATION (HS, XT OR LP OSC CONFIGURATION)TABLE 14-1:CERAMIC RESONATORSNote 1:See T able 14-1 and T able 14-2 for recommendedvalues of C1 and C2.2: A series resistor (R s ) may be required for ATstrip cut crystals.3:RF varies with the crystal chosen.C1(1)C2(1)XTALOSC2OSC1RF (3)Sleep ToLogic PIC16F87XAR s(2)Internal Ranges Tested:Mode Freq.OSC1OSC2XT455 kHz 2.0 MHz 4.0 MHz 68-100 pF 15-68 pF 15-68 pF 68-100 pF 15-68 pF 15-68 pF HS8.0 MHz 16.0 MHz10-68 pF 10-22 pF10-68 pF 10-22 pFThese values are for design guidance only. See notes following Table 14-2.Resonators Used:2.0 MHz Murata Erie CSA2.00MG ± 0.5%4.0 MHz Murata Erie CSA4.00MG ± 0.5%8.0 MHz Murata Erie CSA8.00MT ± 0.5%16.0 MHzMurata Erie CSA16.00MX± 0.5%All resonators used did not have built-in capacitors.OSC1OSC2OpenClock from Ext. SystemPIC16F87XAPIC16F87XADS39582B-page 146 2003 Microchip Technology Inc.TABLE 14-2:CAPACITOR SELECTION FOR CRYSTAL OSCILLATOR14.2.3RC OSCILLATORFor timing insensitive applications, the “RC” device option offers additional cost savings. The RC oscillator frequency is a function of the supply voltage, the resistor (R EXT ) and capacitor (C EXT ) values and the operating temperature. In addition to this, the oscillator frequency will vary from unit to unit due to normal pro-cess parameter variation. Furthermore, the difference in lead frame capacitance between package types will also affect the oscillation frequency, especially for low C EXT values. The user also needs to take into account variation due to tolerance of external R and C components used. Figure 14-3 shows how the R/C combination is connected to the PIC16F87XA.FIGURE 14-3:RC OSCILLATOR MODEOsc TypeCrystal Freq.Cap. RangeC1Cap. RangeC2LP 32 kHz 33 pF 33 pF 200 kHz 15 pF 15 pF XT200 kHz 47-68 pF 47-68 pF 1 MHz 15 pF 15 pF 4 MHz15 pF 15 pF HS 4 MHz 15 pF 15 pF 8 MHz 15-33 pF 15-33 pF 20 MHz15-33 pF15-33 pFThese values are for design guidance only. See notes following this table.Crystals Used32 kHz Epson C-001R32.768K-A ± 20 PPM 200 kHz STD XTL 200.000KHz ± 20 PPM 1 MHz ECS ECS-10-13-1± 50 PPM 4 MHz ECS ECS-40-20-1± 50 PPM 8 MHz EPSON CA-301 8.000M-C ± 30 PPM 20 MHzEPSON CA-301 20.000M-C± 30 PPMNote 1:Higher capacitance increases the stabilityof oscillator but also increases the start-up time.2:Since each resonator/crystal has its owncharacteristics, the user should consult the resonator/crystal manufacturer for appropriate values of external components.3:R s may be required in HS mode, as wellas XT mode, to avoid overdriving crystals with low drive level specification.4:When migrating from other PICmicro ®devices, oscillator performance should be verified.OSC2/CLKOC EXT R EXTPIC16F87XAOSC1F OSC /4Internal Clock V DD V SSRecommended values:3 k Ω ≤ R EXT ≤ 100 k ΩC EXT > 20 pF。
实验二程序清单:(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万年历程序时间:2009-03-05 来源: 作者:Wujieflash 点击:1639 字体大小:【大中小】为了把KS0108系列的液晶吃透,特别制作了这款万年历,感觉效果还是不错的.希望大家分享我的喜悦,毕竟有了更多志同道合的朋友支持,我才能更进一步提高.一,原理介绍说明:1.单片机还是采用PIC中最经典的PIC16F877A,端口多,功能全,特别是他有8K的ROM,这是我选择的主要原因,因为储存液晶的字库需要很大的空间.2.液晶显示还是用的KS0108系列,主要是他性价比高,指令简单,特别是公司也在用.3.时钟/日历芯片用的DALLOS的DS1302芯片,他可以储存从2000-2099年的日历,及实时时钟,可以方便的读写.4.温度测量还是用的DS18B20,这在我上一实例中已经用过,有兴趣可以查阅.5.本万年历可以显示实时时钟,精确到秒,年,月,日,星期,阴历,温度,生肖等,显示的信息量大. 6,可以通过按键自由设定时钟及日历,按"设置"键可以在秒,分,时,日,月,星期,年之间来回切换,要设置的单元以闪烁提醒.通过"+"."-"按键可以把要设置的单元设定到预想状态.二,程序说明:本程序有许多小的模块,现分列如下:1.主程序/**************************************************** 标题:万年历** 作者:Wujieflash ** 日期:2008年1月13日** 说明:包含文件***************************************************/ #include#include "ziku.h"#include "lcd_init.h"#include "ds1302.h"#include "ds18b20.h"#include "keyscan.h"#include "yinli.h"//子程序//LCD显示空白边框子程序void LCDShowTable(){uch i;SlectScreen(1); //写左半屏SetLine(0); //起使页SetColumn(0); //起使列for(i=0;i//显示固定字符子程序void LCDShowGudingWord(){Show8X16_2(0,24,s0);Show8X16_2(0,32,s0);Show8X16(2,1,s0);Show8X16(2,9,s0);Show16X16_3(6,40,ri);Show16X32(2,24,ss0);Show16X32(2,40,ss0);Show8X16_2(0,64,s0);Show8X16_2(0,72,s0);Show8X16_2(0,80,maohao);Show8X16_2(0,88,s0);Show8X16_2(0,96,s0);Show8X16_2(0,104,maohao);Show8X16_2(0,112,s0);Show8X16_2(0,119,s0);Show8X16(2,80,s0);Show8X16(2,88,s0);Show16X16_2(4,64,shiyi);Show16X16_2(4,80,yue);Show16X16_2(4,95,chu);Show16X16_2(4,111,yi);Show16X16_3(6,72,sheng);Show16X16_3(6,88,xiao);Show16X16_3(6,104,shu);Show16X16_2(0,40,nian);Show16X16(4,2,yue);Show16X16_3(6,8,xing);Show16X16_3(6,24,qi);Show16X16(2,96,danwei1);Show8X16_2(0,8,s2);Show8X16_2(0,16,s0);}/*----------------------------------------------------------*/ //TRM1初始化子程序void TMR1init(){//TRM1 INITIALT1CON=0X30; //8分频TMR1IF=0; //清中断标志TMR1IE=1; //使能定时器1中断TMR1L=0XDB; //初始值(定时0.5S)TMR1H=0X0B;TMR1ON=1; //开定时器1}//冒号闪烁子程序void FlashMaohao(){static uch timecount=0;if(TMR1IF==1){TMR1ON=0;TMR1IF=0;TMR1L=0XDB; //重新付初值TMR1H=0X0B;flag++;flag=flag%2; //闪烁标志在0-1间翻转TMR1ON=1;timecount++;if(timecount==120)//1分钟采样一次温度{timecount=0;get_temp(); //温度转换子程序}}if(flag==0){Show8X16_2(0,80,maohao);Show8X16_2(0,104,maohao);}if(flag==1){Show8X16_2(0,80,noshu);//清除Show8X16_2(0,104,noshu);}}//主程序void main(){TMR1init(); //定时器1初始化keyinit(); //键盘初始化LCDinit(); //LCD操作初始化LCDShowTable(); //显示空白表格LCDShowGudingWord(); //显示固定字符//Set1302(DisCash); //设置初始时间(默认写入我写程序的时间) get_temp(); //读取温度while(1){v_Get1302(clock); //读取时间、日历display();YangToYin(clock[6]/16*10+clock[6]&0x0f,clock[4]/16*10+clock[4]&0x0f,clock[3]/16*1 0+clock[3]&0x0f);FlashMaohao(); //冒号闪烁KeyScan(); //键盘扫描}}2.测温程序:/**************************************************** 标题:DS18B20测温** 作者:Wujieflash ** 日期:2008年1月13日** 说明:使用DS18B20芯片测温****************************************************/# define DQ RC3 //定义18B20数据端口# define DQ_DIR TRISC3 //定义18B20D口方向寄存器# define DQ_HIGH() DQ_DIR =1 //设置数据口为输入# define DQ_LOW() DQ = 0; DQ_DIR = 0 //设置数据口为输出unsigned char TLV=0 ; //采集到的温度高8位unsigned char THV=0; //采集到的温度低8位unsigned char TZ=0; //转换后的温度值整数部分//------------------------------------------------//延时函数//系统初始化函数void init(){ADCON1=0X07; //设置A口为普通数字口TRISA=0X00; //设置A口方向为输出//TRISC3=0; //设置D口方向为输出}//-----------------------------------------------//复位DS18B20函数reset(void){char presence=1;while(presence){DQ_LOW() ; //主机拉至低电平delay(2,90); //延时503usDQ_HIGH(); //释放总线等电阻拉高总线,并保持15~60us delay(2,8); //延时70usif(DQ==1) presence=1; //没有接收到应答信号,继续复位else presence=0; //接收到应答信号delay(2,70); //延时430us}}//-----------------------------------------------//写18b20写字节函数void write_byte(uch val){uch i;uch temp;for(i=8;i>0;i--){temp=val&0x01; //最低位移出DQ_LOW();NOP();NOP();NOP();NOP();NOP(); //从高拉至低电平,产生写时间隙if(temp==1) DQ_HIGH(); //如果写1,拉高电平delay(2,7); //延时63usDQ_HIGH();NOP();NOP();val=val>>1; //右移一位}}//------------------------------------------------//18b20读字节函数uch read_byte(void){uch i;uch value=0; //读出温度static bit j;for(i=8;i>0;i--){value>>=1;DQ_LOW();NOP();NOP();NOP();NOP(); //6usDQ_HIGH(); //拉至高电平NOP();NOP();NOP(); //4usj=DQ;if(j) value|=0x80;delay(2,7); //63us}return(value);}//-------------------------------------------------//启动温度转换函数void get_temp(){int i;DQ_HIGH();reset(); //复位等待从机应答write_byte(0XCC); //忽略ROM匹配write_byte(0X44); //发送温度转化命令for(i=10;i>0;i--){delay(201,132); //调用多次延迟函数,确保温度转换完成所需要的时间}reset(); //再次复位,等待从机应答write_byte(0XCC); //忽略ROM匹配write_byte(0XBE); //发送读温度命令TLV=read_byte(); //读出温度低8THV=read_byte(); //读出温度高8位DQ_HIGH(); //释放总线TZ=(TLV>>4)|(THV<<4);}3.日历显示程序/*************************************************** * 标题:DS1302读写** 作者:Wujieflash ** 日期:2008年1月14日** 说明:日历显示范围:2000年--2099年****************************************************/ #define RST RC0#define SCLK RC1#define IO RC2uch flag=0;uch second=1,minute=1,hour=1,year=1,month=1,date=1,day=1; uch clock[]={0};uch DisCash[]={0x00,0x30,0x09,0x16,0x01,0x03,0x09};/////往1302写入1Byte数据////////////////////////void RTInputByte(uch d){uch i;TRISC=0x00;for(i=8; i>0; i--){IO = d&0x01; //取最低位SCLK = 1; //上升沿发送SCLK = 0; //恢复d = d >> 1;}}///////从1302读取1Byte数据////////////////////////uch RTOutputByte(void){uch i,val=0;TRISC2=1; //设置为输入for(i=8; i>0; i--){val = val >>1;if(IO)val=val|0x80;// 从最低位开始接收SCLK = 1; //下降沿接收SCLK = 0;}return(val);}///////先写地址,后写命令/数据////////////////////////// void W1302(uch ucAddr, uch ucDa){RST = 0;SCLK = 0;RST = 1; //打开DS1302RTInputByte(ucAddr); // /* 地址,命令*/RTInputByte(ucDa); // /* 写1Byte数据*/SCLK = 1;RST = 0; //关闭DS1302}///////先写地址,后读命令/数据////////////////////////uch R1302(uch ucAddr){uch ucData;RST = 0;SCLK = 0;RST = 1;RTInputByte(ucAddr); // /* 地址,命令*/ucData = RTOutputByte(); // /* 读1Byte数据*/ SCLK = 1;RST = 0;return(ucData);}/////////向1302写入秒分时日月星期年*/////////////void Set1302(uch *pClock){uch i;uch ucAddr = 0x80; //起使地址W1302(0x8e,0x00); ///* 控制命令,WP=0,允许写操作*/ for(i =7; i>0; i--){W1302(ucAddr,*pClock); ///* 秒分时日月星期年*/ pClock++;ucAddr +=2; //写地址加2}W1302(0x8e,0x80); // /* 控制命令,WP=1,写保护*/}////////从1302读出秒分时日月星期年*////////////////// void v_Get1302(unsigned char ucCurtime[]){unsigned char i;unsigned char ucAddr = 0x81;for(i=0;i/////////与LCD的显示接口//////////////////////void display(){uch i;for(i=0;i4.按键扫描与服务程序/*************************************************** * 标题:按键扫描和服务** 作者:Wujieflash ** 日期:2008年1月17日** 说明:当按键按下,选中的单元就会闪烁****************************************************/ uch k=0;//键盘初始化子程序void keyinit(){TRISD0=1;TRISD0=1;TRISD0=1;}/*----------------------------------------------------------*/ //键盘扫描子程序void KeyScan(){int d;if(RD0==0) //设置键按下{k++; //选定入口值k=k%8;}while(1){if(RD0==1)break;//等待按键松开}switch(k)//键盘服务入口{case 1://设置秒{d=R1302(0x81);//读取秒d=d/16*10+d%16;//转换为16进制second=flag; //设置秒的闪烁标志minute=1; //其余变量不闪烁hour=1;year=1;month=1;date=1;day=1;if(second==0) //闪烁{Show8X16_2(0,111,noshu);Show8X16_2(0,119,noshu);}if(RD1==0) //秒数值加1{d++;if(d>0x3b)d=0;//大于59就为0 d=d/10*16+d%10;W1302(0x80,d);//写入DS1302 while(1){if(RD1==1)break;//等待键松开}}if(RD2==0)//数值减1{d--;if(d0x3b)d=0;d=d/10*16+d%10;W1302(0x82,d);while(1){if(RD1==1)break;}}if(RD2==0){d--;if(d0x17)d=0;d=d/10*16+d%10;W1302(0x84,d);while(1){if(RD1==1)break;}}if(RD2==0){d--;if(d0x1f)d=1;d=d/10*16+d%10;W1302(0x86,d); while(1){if(RD1==1)break; }}if(RD2==0){d--;if(d0x0c)d=1;d=d/10*16+d%10; W1302(0x88,d); while(1){if(RD1==1)break; }}if(RD2==0){d--;if(d0x07)d=1;d=d/10*16+d%10; W1302(0x8a,d); while(1){if(RD1==1)break; }}if(RD2==0){d--;if(d0x63)d=0;d=d/10*16+d%10; W1302(0x8c,d); while(1){if(RD1==1)break;}}if(RD2==0){……5.液晶显示程序/**************************************************** 标题:LCD操作** 作者:Wujieflash ** 日期:2008年1月12日** 说明:KS0108系列液晶不带字库****************************************************/#include#define E RA0 //液晶使能端#define RW RA1 //读写控制端#define DI RA2 //数据/指令通道#define CSA RA5 //片选#define CSB RA3 //片选#define nop() asm("nop")////////////////////////基本子函数/////////////////////////延时void delay(char x,char y){char z;do{z=y;do{;}while(--z);}while(--x);}//其指令时间为:7+(3*(Y-1)+7)*(X-1)如果再加上函数调用的call 指令、页面设定、传递参数花掉的7 个指令。