
<p>第5章 PIC16F877的外围功能模块<p><br/>5.1.2 简单应用实例<br/>该例用于令与PORTD口相连的8个发光二极管前4个点亮,后4个熄灭。在调试程序前,应使与PORTD口相连的8位拔码开关拔向相应的位置。<br/>例5.1 PORTD输出<p><p>#include <pic.h><p>main()<p>{<p> TRISD=0X00; /*TRISD寄存器被赋值,PORTD每一位都为输出*/<p>while(1); /*循环执行点亮发光二极管的语句*/<p> {<p> PORTD=0XF0; /*向PORTD送数据,点亮LED(由实验模板*/<p>/*的设计决定相应位置低时LED点亮)。*/<p>}<p>}<p><br/><p>5.2.1 MSSP模块SPI方式功能简介<p> 下面是一段简单的SPI初始化例程,用于利用SPI工作方式输出数据的场合。<p>例5.2 SPI初始化程序<p>/*spi初始化子程序*/<p>void SPIINIT()<p>{<p> PIR1=0; /*清除SPI中断标志*/ <p> SSPCON=0x30; /* SSPEN=1;CKP=0 , FOSC/4 */<p> SSPSTAT=0xC0;<p> TRISC=0x00; /*SDO引脚为输出,SCK引脚为输出*/<p>}<p>5.2.3 程序清单<p>下面给出已经在实验板上调试通过的一个程序,可作为用户编制其它程序的参考。<p>#include <pic1687x.h><p>/*该程序用于在8个LED上依次显示1~8等8个字符*/<p>static volatile int table[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x7f,0xbf,0x89,0xff};<p>volatile unsigned char data; <p>#define PORTAIT(adr,bit) ((unsigned)(&adr)*8+(bit)) /*绝对寻址位操作指令*/<p>static bit PORTA_5 @ PORTAIT(PORTA,5); <p>/*spi初始化子程序*/<p>void SPIINIT()<p>{<p> PIR1=0; <p> SSPCON=0x30; /* SSPEN=1;CKP=0 , FOSC/4 */<p> SSPSTAT=0xC0;<p> TRISC=0x00; /*SDO引脚为输出,SCK引脚为输出*/<p>}<p>/*系统各输入输出口初始化子程序*/<p>void initial()<p>{<p>TRISA=0x00; /*A口设置为输出*/<p> INTCON=0x00; /*关闭所有中断*/<p> PORTA_5=0; /*LACK送低电平,为锁存做准备*/<p>}<p>/*SPI发送子程序*/<p>void SPILED(int data)<p>{<p> SSPBUF=data; /*启动发送*/<p> do<p> {<p>;<p> }while(SSPIF==0); /*等待发送完毕*/<p>SSPIF=0; /*清除SSPIF标志*/<p>}<p>/*主程序*/<p>main()<p>{<p> unsigned I;<p> initial(); /*系统初始化*/<p> SPIINIT() ; /*SPI初始化*/ <p> for(i=8;i>0;i--) /*连续发送8个数据*/<p> {<p> data=table[i]; /*通过数组的转换获得待显示的段码*/ <p> SPILED(data); /*发送显示段码显示*/ <p> }<p> PORTA_5=1; /*最后给锁存信号,代表显示任务完成*/<p>}<p>5.3.3 程序清单<p> 下面给出已经在实验板上调试通过的程序,可作为用户编制其它程序的参考。有关显示部分的SPI初始化,请读者参考5.2节。<p>#include <pic.h><p>/*该程序用于按下相应的键时,在第一个8段LED上显示相应的1~4的字符*/<p>#define PORTAIT(adr,bit) ((unsigned)(&adr)*8+(bit)) /*绝对寻址位操作指令*/<p>static bit PORTA_5 @ PORTAIT(PORTA,5); <p>#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit)) /*绝对寻址位操作指令*/<p>static bit PORTB_5 @ PORTBIT(PORTB,5);<p>static bit PORTB_4 @ PORTBIT(PORTB,4);<p>static bit PORTB_1 @ PORTBIT(PORTB,1) ;<p>static bit PORTB_2 @ PORTBIT(PORTB,2) ;<p>unsigned int I;<p>unsigned char j;<p>int data;<p>/*spi初始化子程序*/<p>void SPIINIT()<p>{<p> PIR1=0;<p> SSPCON=0x30; <p> SSPSTAT=0xC0;<p> TRISC=0xD7; /*SDO引脚为输出,SCK引脚为输出*/<p>}<p>/*系统各输入输出口初始化子程序*/<p>void initial()<p>{<p> TRISA=0xDF;<p> TRISB=0XF0; /*设置与键盘有关的各口的数据方向*/<p> INTCON=0x00; /*关闭所有中断*/<p> data=0X00; /*待显示的寄存器赋初值*/<p> PORTB=0X00; /*RB1 RB2 先送低电平*/<p> j=0;<p>}<p>/*软件延时子程序*/<p>void DELAY()<p>{<p> for(i = 6553; --i ;)<p> continue;<p>}<p>/*键扫描子程序*/<p>int KEYSCAN()<p>{ <p>while(1)<p>{<p> if ((PORTB_5==0)||(PORTB_4==0))<p> break;<p>} /*等待有键按下*/<p> DELAY(); /*软件延时*/<p> if ((PORTB_5==0)||(PORTB_4==0))<p> KEYSERVE(); /*如果仍有键按下,则调用键服务子程序*/<p> else j=0x00; /*如果为干扰,则令返回值为0*/<p> return(j);<p>} <p>/*键服务子程序*/<p>int KEYSERVE()<p>{<p> PORTB=0XFD ;<p> if(PORTB_5==0) j=0X01;<p> if(PORTB_4==0) j=0X03;<p> PORTB=0XFB;<p> if(PORTB_5==0) j=0X02;<p> if(PORTB_4==0) j=0X04;/*以上根据按下的键确定相应的键值*/<p> PORTB=0X00; /*恢复PORTB的值*/<p>while(1)<p>{<p> if((PORTB_5==1)&&(PORTB_4==1)) break;/*等待键盘松开*/<p> }<p> return(j);<p>}<p>/*SPI发送子程序*/<p>void SPILED(int data)<p>{<p> SSPBUF=data; /*启动发送*/<p> do<p> {<p> ;<p> }while(SSPIF==0); /*等待发送完毕<p> SSPIF=0;<p>}<p>/*主程序*/<p>main()<p>{<p>static int table[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x7f,0xbf,0x89,0xff};<p> initial();/*系统初始化*/ <p> SPIINIT() ;/*SPI初始化*/ <p>while(1)<p>{ <p>刚接触pic单片机 使用的是MPLAB IDE 对于配置字的要求可以通过软件进行设置 <br/>也可以用__CONFIG();进行设置<br/>但是发现官网上用的是MOLAB X IDE 对于配置字的格式要求<br/>变成了#pragma 当然也可以通过软件的窗口>>pic存储器视图>>配置字<br/>对配置字进行设置 <br/>XC8对于中断的格式也有了变化 __interrupt(优先级)<br/>#pragma config FOSC = INTRC_CLKOUT// Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)<br/>#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)<br/>#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)<br/>#pragma config MCLRE = ON // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)<br/>#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)<br/>#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)<br/>#pragma config BOREN = ON // Brown Out Reset Selection bits (BOR enabled)<br/>#pragma config IESO = OFF // Internal External Switchover bit (Internal/External Switchover mode is disabled)<br/>#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)<br/>#pragma config LVP = OFF // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)<br/><br/>// CONFIG2<br/>#pragma config BOR4V = BOR40V // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)<br/>#pragma config WRT = OFF // Flash Program Memory Self Write Enable bits (Write protection off)<br/><br/>// #pragma config statements should precede project file includes.<br/>// Use project enums instead of #define for ON and OFF. <p>//=======================================用户配置区,供用户修改===========================================<p><br/><p>#define TIME2 1000 //长按键时间设置,单位ms ,1000 = 1s 范围:1~10s<p><br/><p>//=========================================================================================================<p><br/><p><br/><p><br/><p><br/><p><br/><p><br/><p><br/><p><br/><p><br/><p>// 以下为代码区,请勿改动! *<p>// 以下为代码区,请勿改动! *<p>// 以下为代码区,请勿改动! *<p>// 以下为代码区,请勿改动! *<p>// 以下为代码区,请勿改动! *<p>// 以下为代码区,请勿改动! *<p>// 以下为代码区,请勿改动! *<p><br/><p>//=============================================硬件连接示意===============================================<p>//<p>// ___短 _ 长 _______ <p>// |_| |_________| PIC10F200/202<p>// +---------+<p>// KEY 长/短按键 ---|GP0 GP3|---<p>// | |<p>// |GND VDD|<p>// | | __ ___ <p>// 长按键翻转输出 ---|GP1 GP2|---短按键翻转输出 _| |____| |____<p>// +---------+<p>// __________ _____________ <p>// _| |___________| |____<p>//<p>//--------------------------------------------------------------------------------------------------------<p>/*<p> <p> 长/短按键IO口电平翻转程序<p><br/><p><br/><p> 说明:1.该程序通过检测GP0管脚的有效按键长短,循环翻转GP2和GP1管脚的输出电平高低。<p> 每检测到一个短按键,则对GP2管脚输出电平进行一次翻转,每检测到一个长按键,<p> 则对GP1管脚输出电平进行一次翻转。 <p><br/><p> 2.按键是带有状态机的键盘扫描程序,可有效对按键消抖,抗干扰能力极强。<p><br/><p> 3.长按键的时间可通过程序顶端的参数进行方便的设置,以满足现场需求。<p> <p> 4.GP1、GP2在单片机默认状态和复位后输出电平为低。<p><br/><p> 5.待机功耗为400uA(@5V),长按键功耗为500uA(@5V)。<p><br/><p> 6.已启用内部弱上拉,按键可以不加上拉电阻,如果要保证信号可靠,可以加上拉电阻,<p> 建议选择>=100K的电阻,以降低长时间按下按键在电阻上的功耗。<p><br/><p><br/><p> 日期:2014/09/04 版本:V2.0<p> <p>*/<p><br/><p>//=========================================================================================================<p><br/><p><br/><p><br/><p>#include <pic.h> //本代码可支持单片机型号:PIC10F200/202<p><br/><p>#define Key_Read_T 25 //等间隔读取键值,单位ms<p><br/><p>#define KEY_IO GP0 //按键信号输入<p>#define Short_Out GP1 //短按按键响应数出口<p><br/><p>bit short_out; //记录Short_Out当前状态<p>bit short_IF; //短按响应标志<p><br/><p>#define Long_Out GP2 //长按按键响应数出口<p><br/><p>bit long_out; //记录Long_Out当前状态<p>bit long_IF; //长按响应标志<p><br/><p>unsigned char KEY_State=0; /*按键的状态变量*/<p><br/><p><br/><p>#define NOKEY 0<p>#define PUSH_KEY 1<p>#define LONG_PUSH 2<p><br/><p>#define INITIAL_25MS 161 //相对于本系统与定时器时钟,本数据为固定值。定时器增计数,计数周期为256us,计97个数约为25mS。256-97+2=161<p><br/><p>/<p>* 名 称:Key_ScanIO()<p>* 功 能:扫描键盘IO口并判断按键事件<p>* 入口参数:Ticklong:长按键有效时长,单位ms<p>* 出口参数:无<p>* 说 明: 该函数需要每隔25(Key_Read_T)ms,调用一次。最好放在定时中断内执行。<p> 如果中断间隔太长,可能丢键;间隔太短不能消除抖动。<p>/<p>void Key_ScanIO(int Ticklong)<p>{ <p> static unsigned int KeyTimerS;<p> <p>//===============================按键======================================== <p> if(KEY_State==PUSH_KEY) KeyTimerS++; /*定时器,时间间隔25ms*/<p> else KeyTimerS=0;<p> <p> switch(KEY_State) //根据按键的状态决定程序分支<p> {<p> case NOKEY: //------------------在未按键状态下--------------------------<p> { //若键被按下,按键状态变为"短按状态"。<p> if(KEY_IO==0) KEY_State=PUSH_KEY;<p> break;<p> }<p> case PUSH_KEY: //-------------按键处于"短按状态"时------------------------<p> {<p> if(KEY_IO!=0) //若键被释放,认为是一次短按键<p> {<p> KEY_State=NOKEY; //并回到"未按下状态" <p> short_IF = 0; <p> long_IF = 0; <p> }<p> else if(KeyTimerS>Ticklong) //若按键时间超过Ticks毫秒,认为是一次长按键,<p> {<p> KEY_State=LONG_PUSH; // 按键状态变为"长按状态" <p> } <p> break; <p> }<p> case LONG_PUSH: //------------按键处于"长按状态"时--------------------<p> {<p> if(KEY_IO!=0) //若键被释放,回到未按键状态<p> {<p> KEY_State=NOKEY;<p> short_IF = 0; <p> long_IF = 0; <p> } <p> break; <p> }<p> } <p>}<p><br/><p>/<p>* 名 称:Key_Answer()<p>* 功 能:根据按键状态作出响应,控制IO管脚输出电平翻转<p>* 入口参数:Ticklong:长按键有效时长,单位ms<p>* 出口参数:无<p>/<p>void Key_Answer(void)<p>{<p> if((KEY_State==PUSH_KEY)&&(short_IF == 0)) <p> {<p> short_out = ~short_out;<p> Short_Out = short_out;<p> short_IF = 1; <p> }<p> if((KEY_State==LONG_PUSH)&&(long_IF == 0)) <p> {<p> long_out = ~long_out;<p> Long_Out = long_out;<p> long_IF = 1;<p> } <p>}<p><br/><p>/<p>名 称:main()<p>功 能:主程序<p>入口参数:无<p>出口参数:无<p>*/<p>void main()<p>{<p> <p> //设置时钟周期Fosc = 4MHz,系统时钟,无法设置<p> OPTION = 0x97; //复位值0xFF。TIMER0的时钟源是Fosc/4,1us。TIMER0 256预分频,256us<p>// CMCON0 = 0xE1;<p><br/><p> TRISGPIO = 0x09; //GP1、GP2配置为输出。0为输出,1为输入<p> short_out = 0;<p> Short_Out = short_out;<p> long_out = 0; <p> Long_Out = long_out; //为输出赋初值 <p><br/><p> TMR0 = INITIAL_25MS; //增计数,计数周期为256us,计97个数约为25mS。256-125+2=97 <p><br/><p> while(1)<p> {<p> #asm<p> CLRWDT <p> #endasm <p>程序代码:<p><br/><p>#include<pic.h><p>#define uchar unsigned char<p>#define uint unsigned int<p>__CONFIG(HS&WDTDIS);<p>#include "Drive_Serial.h"<p>uchar line1_data[] = {"顶顶电子欢迎您!"};<p>uchar line2_data[] = {" www*ddmcu*com "};<p>uchar line3_data[] = {"DD-900实验开发板"};<p>uchar line4_data[] = {"TEL: "};<p>/端口设置函数/<p>void port_init(void)<p>{<p> TRISC = 0x00;<p> TRISD = 0x00; <p>} <p>/以下是闪烁三次函数/<p>void lcd_flash()<p>{<p> Delay_ms(1000); //控制停留时间 <p> lcd_wcmd(0x08); //关闭显示 <p> Delay_ms(500); //延时0.5s <p> lcd_wcmd(0x0c); //开显示 <p> Delay_ms(500); //延时0.5s<p> lcd_wcmd(0x08); //关闭显示 <p> Delay_ms(500); //延时0.5s <p> lcd_wcmd(0x0c); //开显示 <p> Delay_ms(500); //延时0.5s<p> lcd_wcmd(0x08); //关闭显示 <p> Delay_ms(500); //延时0.5s <p> lcd_wcmd(0x0c); //开显示 <p> Delay_ms(500); //延时0.5s<p>} <p>/以下是主函数/<p>void main()<p>{<p> uchar i;<p> port_init();<p> Delay_ms(100); //上电,等待稳定 <p> lcd_init(); //初始化LCD<p> while(1)<p> {<p> LocateXY(0,0); //设置显示位置为第0行,0列<p> for(i=0;i<16;i++)<p> {<p> lcd_wdat(line1_data[i]);<p> Delay_ms(100); //每个字符停留的时间为100ms<p> }<p> LocateXY(0,1); //设置显示位置为第1行第0列<p> for(i=0;i<16;i++)<p> {<p> lcd_wdat(line2_data[i]);<p> Delay_ms(100);<p> }<p> LocateXY(0,2); //设置显示位置为第2行第0列<p> for(i=0;i<16;i++)<p> {<p> lcd_wdat(line3_data[i]);<p> Delay_ms(100);<p> }<p> LocateXY(0,3); //设置显示位置为第3行第0列<p> for(i=0;i<16;i++)<p> {<p> lcd_wdat(line4_data[i]);<p> Delay_ms(100);<p> }<p> Delay_ms(1000); //停留1s<p> lcd_flash(); //闪烁三次<p> lcd_clr(); //清屏<p> Delay_ms(2000); <p> }<p>}<p><br/>
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/203180.html