网站公告列表     本站全新改版正在建设中!  [admin  2007年10月22日]        
加入收藏
设为首页
联系站长
您现在的位置: 东方电子科技有限公司 >> 技术文章 >> PIC单片机更多 >> 文章正文
  [组图]PIC16F877的外围功能模块           ★★★ 【字体:
PIC16F877的外围功能模块
PIC16F877的外围功能模块
作者:佚名    文章来源:本站原创    点击数:    更新时间:2007-10-17    

PIC16F877的外围功能模块

5.1.2  简单应用实例

    该例用于令与PORTD口相连的8个发光二极管前4个点亮,后4个熄灭。在调试程序前,应使与PORTD口相连的8位拔码开关拔向相应的位置。

5.1   PORTD输出

       #include  <pic.h>

main()

{

       TRISD=0X00                   /*TRISD寄存器被赋值,PORTD每一位都为输出*/

while(1)                           /*循环执行点亮发光二极管的语句*/

       {

              PORTD=0XF0          /*PORTD送数据,点亮LED(由实验模板*/

/*的设计决定相应位置低时LED点亮)。*/

}

}

 

5.2.1  MSSP模块SPI方式功能简介

       下面是一段简单的SPI初始化例程,用于利用SPI工作方式输出数据的场合。

5.2  SPI初始化程序

/*spi初始化子程序*/

void       SPIINIT()

{

       PIR1=0                                   /*清除SPI中断标志*/        

       SSPCON=0x30                /* SSPEN=1CKP=0 FOSC/4 */

       SSPSTAT=0xC0

       TRISC=0x00                    /*SDO引脚为输出,SCK引脚为输出*/

}

5.2.3  程序清单

下面给出已经在实验板上调试通过的一个程序,可作为用户编制其它程序的参考。

#include         <pic1687x.h>

/*该程序用于在8LED上依次显示1~88个字符*/

static volatile int table[20]={0xc00xf90xa40xb00x990x920x820XD80x800x900x880x830xc60xa10x860x8e0x7f0xbf0x890xff}

volatile    unsigned        char       data

#define   PORTAIT(adrbit)  ((unsigned)(&adr)*8+(bit))       /*绝对寻址位操作指令*/

static       bit PORTA_5 @ PORTAIT(PORTA5)

/*spi初始化子程序*/

void        SPIINIT()

{

       PIR1=0             

       SSPCON=0x30                /* SSPEN=1CKP=0 FOSC/4 */

       SSPSTAT=0xC0

       TRISC=0x00                    /*SDO引脚为输出,SCK引脚为输出*/

}

/*系统各输入输出口初始化子程序*/

void        initial()

{

TRISA=0x00                    /*A口设置为输出*/

       INTCON=0x00                /*关闭所有中断*/

       PORTA_5=0                            /*LACK送低电平,为锁存做准备*/

}

/*SPI发送子程序*/

void              SPILED(int data)

{

       SSPBUF=data                   /*启动发送*/

       do

       {

       }while(SSPIF==0)            /*等待发送完毕*/

SSPIF=0                          /*清除SSPIF标志*/

}

/*主程序*/

main()

{

       unsigned  I;

       initial()                             /*系统初始化*/

       SPIINIT()                               /*SPI初始化*/     

      for(i=8i>0i--)                /*连续发送8个数据*/

      {

              data=table[i]                     /*通过数组的转换获得待显示的段码*/    

              SPILED(data)            /*发送显示段码显示*/        

      }

       PORTA_5=1                            /*最后给锁存信号,代表显示任务完成*/

}

5.3.3  程序清单

      下面给出已经在实验板上调试通过的程序,可作为用户编制其它程序的参考。有关显示部分的SPI初始化,请读者参考5.2节。

#include         <pic.h>

/*该程序用于按下相应的键时,在第一个8LED上显示相应的14的字符*/

#define   PORTAIT(adrbit)  ((unsigned)(&adr)*8+(bit))       /*绝对寻址位操作指令*/

static       bit  PORTA_5  @  PORTAIT(PORTA5)

#define    PORTBIT(adr bit)     ((unsigned)(&adr)*8+(bit))   /*绝对寻址位操作指令*/

static       bit  PORTB_5  @  PORTBIT(PORTB5)

 

 

static      bit  PORTB_4  @  PORTBIT(PORTB4)

 

static       bit  PORTB_1  @  PORTBIT(PORTB1)   

static       bit  PORTB_2  @  PORTBIT(PORTB2)   

unsigned        int    I

unsigned        char j

int  data

 /*spi初始化子程序*/

void      SPIINIT()

{

       PIR1=0

       SSPCON=0x30 

       SSPSTAT=0xC0

       TRISC=0xD7                   /*SDO引脚为输出,SCK引脚为输出*/

}

/*系统各输入输出口初始化子程序*/

void      initial()

{

       TRISA=0xDF

       TRISB=0XF0                   /*设置与键盘有关的各口的数据方向*/

       INTCON=0x00                /*关闭所有中断*/

       data=0X00                       /*待显示的寄存器赋初值*/

       PORTB=0X00                  /*RB1 RB2 先送低电平*/

       j=0

}

/*软件延时子程序*/

void        DELAY()

{

       for(i = 6553 --i )

       continue

}

/*键扫描子程序*/

int           KEYSCAN()

{    

while(1)

{

       if ((PORTB_5==0)||(PORTB_4==0))

       break

}                                               /*等待有键按下*/

       DELAY()                         /*软件延时*/

       if ((PORTB_5==0)||(PORTB_4==0))

              KEYSERVE()            /*如果仍有键按下,则调用键服务子程序*/

       else  j=0x00                      /*如果为干扰,则令返回值为0*/

       return(j)

}    

/*键服务子程序*/

int           KEYSERVE()

{

       PORTB=0XFD      

       if(PORTB_5==0)    j=0X01

       if(PORTB_4==0)    j=0X03

       PORTB=0XFB

       if(PORTB_5==0)    j=0X02

       if(PORTB_4==0)    j=0X04/*以上根据按下的键确定相应的键值*/

       PORTB=0X00                  /*恢复PORTB的值*/

while(1)

{

              if((PORTB_5==1)&&(PORTB_4==1)) break/*等待键盘松开*/

       }

       return(j)

}

/*SPI发送子程序*/

void               SPILED(int data)

{

       SSPBUF=data                   /*启动发送*/

       do

       {

         

       }while(SSPIF==0)            /*等待发送完毕

       SSPIF=0

}

/*主程序*/

main()

{

static  int table[20]={0xc00xf90xa40xb00x990x920x820XD80x800x900x880x830xc60xa10x860x8e0x7f0xbf0x890xff}

       initial()/*系统初始化*/            

       SPIINIT()      /*SPI初始化*/         

while(1)

{

       KEYSCAN()

       if(j!=0)                                /*如果j=0,证明先前的按键为干扰,则不予显示*/

{

              data=table[j]

              PORTA_5=0                     /*LACK信号清0,为锁存做准备*/

              SPILED(data)

              PORTA_5=1                     /*最后给锁存信号,代表显示任务完成*/

}

  }

}

5.4.1   PORTB端口“电平变化中断”简介

5.3   PORTB口“电平变化中断”初始化子程序

/*B口“电平变化中断”初始化子程序*/

void              PORTBINT( )

{

       TRISB=0XF0                   /*设置相应口的输入输出方式*/

       OPTION=0x7F                /*B口弱上拉有效*/

       PORTB=0X00                  /*RB1RB2 先送低电平*/

       RBIE=1                           /*B口变位中断允许 */

       PORTB=PORTB               /*B口的值,以锁存旧值,为变位中断创造条件*/

}

5.4.3  程序清单

      下面给出一个调试通过的例程,以供读者参考。有关显示的部分请读者参考前面章节。该程序中寄存器的位都用头文件中定义的位,如RB5表示PORTB的第5位,而不像前面几节那样自己定义。

       #include  <pic.h>

/*该程序用于通过PORTB"电平变化中断"进行键盘的识别。*/

/*程序设置一个键值寄存器j,当按下S9键时j=1,按下S11键时 */

/*j=2,按下S10键时,j=3,按下S12键时j=4*/

unsigned        char        data

unsigned        int           I

unsigned        char        j

const char table[20]={0xc00xf90xa40xb00x990x920x820XD80x800x900x880x830xc60xa10x860x8e0x7f0xbf0x890xff}

/*B口“电平变化中断”初始化子程序*/

void              PORTBINT()

{

       TRISB=0XF0                   /*设置相应口的输入输出方式*/

       OPTION=0x7F

       PORTB=0X00                  /*RB1 RB2 先送低电平*/

       RBIE=1                           /*B口变位中断允许 */

       PORTB=PORTB               /*B口的值,为变位中断创造条件*/

}

/*spi初始化子程序*/

void              SPIINIT()

{

       PIR1=0

       SSPCON=0x30 

       SSPSTAT=0xC0

       TRISC=0xD7                   /*SDO引脚为输出,SCK引脚为输出*/

}

/*系统各输入输出口初始化子程序*/

void        initial()

{

       TRISA=0xDF

       INTCON=0x00                /*关闭所有中断*/

       data=0X00                       /*待显示的寄存器赋初值*/

}

/*键服务子程序*/ 

void        KEYSERVE()

{

       PORTB=0XFD      

       if(RB5==0)     j=0X01

       if(RB4==0)     j=0X03

       PORTB=0XFB      

       if(RB5==0)     j=0X02

       if(RB4==0)     j=0X04              /*以上通过逐行逐列扫描,以确定是何键按下*/    

       PORTB=0X00                  /*恢复PORTB的值*/

}

/*软件延时子程序*/

void              DELAY()

{

       for(i = 6553 --i )

       continue

}

/*SPI发送子程序*/

void       SPILED(int data)

{

       SSPBUF=data                   /*启动发送*/

       do

       {

         

       }while(SSPIF==0)

       SSPIF=0

}

void        IDEDIS()

{

       KEYSERVE()                   /*进行键盘的识别*/

       data=table[j]                            /*获得需要送出显示的段码*/

       RA5=0                             /*LACK信号清0,为锁存做准备*/

       SPILED(data)

       RA5=1                             /*最后给一个锁存信号,代表显示任务完成*/

}

/*中断服务程序*/

void interrupt  keyint(void)

{

       DELAY()                         /*软件延时*/

       if ((RB5==0)||(RB4==0))              /*该语句除了能够确认按键是否为干扰外,*/

                                                 /*还可以屏蔽一次键松开时引起的中断*/

       IDEDIS()                         /*键识别和显示模块*/

       PORTB=PORTB               /*B口的值,改变中断发生的条件,避免键*/

                                                 /*一直按下时,连续进行键识别*/    

       RBIF=0                           /*键扫描时可能会产生"电平变化"而使RBIF*/

                                                 /*1,再清除一次RBIF以避免额外中断*/

}

main()

{

       initial()                             /*系统初始化*/

       PORTBINT()                   /*B口变位中断初始化*/

       SPIINIT()                               /*利用SPI显示初始化*/

       ei()                                  /*总中断允许*/

while(1)

       {

             

       }                                        /*等待中断*/

}

5.5.2  程序清单

       下面给出一个调试通过的例程,可作为读者的参考。调试该程序把模板J7上的短路跳针拔下,以免产生冲突。

#include  <pic1687x.h>

volatile    unsigned        char       data

/*spi初始化子程序*/

 void      SPIINIT()

{

       PIR1=0

       SSPCON=0x30                /* SSPEN=1CKP=0 FOSC/4 */

       SSPSTAT=0xC0

       TRISC=0x10                    /*SDI引脚为输入,SCK引脚为输出*/

}

/*系统各输入输出口初始化子程序*/

void        initial()

{

       TRISA=0x00

       TRISD=0x00                   /*D口为输出方式*/

       INTCON=0x00                /*关闭所有中断*/

}

/*SPI接收子程序*/

 int        SPIIN()

{    

       RA4=0                             /*74HC165并行置数使能,将8位开关量置入器件*/

                                                 /* (LOAD为低电平时8位并行数据置入74HC165)*/

       RA4=1                             /*74HC165移位置数使能(LOAD为高电平时芯*/

                                                 /*片才能串行工作)*/

       SSPBUF=0                       /*启动SPI,此操作只用于清除SSPSTAT

                                                 *BF位,因此W中的实际数据无关紧要*/

       do{

          

       }while(SSPIF==0)            /*查询数据接收完毕否?*/

       SSPIF=0

       data=SSPBUF

       return(data)                      /*返回接收到的数据*/

}

/*SPI接收的数据通过D口显示在8个发光二极管上的子程序*/

void        SPIOUT(int data)

{

       PORTD=~data

}

/*主程序*/

main( )

{

       initial()                             /*系统初始化*/

       SPIINIT()                        /*SPI初始化*/

 while(1)

  {

       SPIIN()                                  /*SPI接收外部数据*/

       SPIOUT(data)                  /*送出数据显示*/

  }

}

5.6.1  CCP模块的PWM工作方式简介

  下面给出一个CCP模块设置为PWM操作时的初始化程序

5.4  CCP模块设置为PWM方式时的初始化程序

/*CCP1模块的PWM工作方式初始化子程序*/

void      CCP1INIT()

{

 CCPR1L=0X7F

 CCP1CON=0X3C                  /*设置CCP1模块为PWM工作方式,且其工作循环

                                                 *的低2位为11,高8位为01111111=7F*/

 INTCON=0X00                            /*禁止总中断和外围中断*/

 PR2=0XFF                                   /*设置PWM的工作周期*/

 TRISC=0XFB                        /*设置CCP1引脚为输出方式*/

}

该初始化子程序设置CCP1模块输出分辨率为10位的PWM波形,且占空比为50%

5.6.3  程序清单

      下面给出一个调试通过的例程,可作为读者编制程序的参考。

#include  <pic.h>

/*该程序用于使CCP1模块产生分辨率为10位的PWM波形,占空比为50%*/

 

/*CCP1模块的PWM工作方式初始化子程序*/

void CCP1INIT()

{

 CCPR1L=0X7F

 CCP1CON=0X3C                  /*设置CCP1模块为PWM工作方式,且其工作

                                                 *循环的低2位为11,高8位为01111111=7F*/

 INTCON=0X00                            /*禁止总中断和外围中断*/

 PR2=0XFF                                   /*设置PWM的工作周期*/

 TRISC=0XFB                        /*设置CCP1引脚为输出方式*/

}

/*主程序*/

main()

{

       CCP1INIT()                            /*CCP1模块的PWM工作方式初始化*/

      T2CON=0X04                  /*打开TMR2,且使其前分频为0

                                                     *同时开始输出PWM波形*/

do

       {

             

       }while(1)                         /*系统开始输出PWM波形。如果系统是

                                                 *多任务的,则可以在此执行其它任务,而

                                                 *不会影响PWM波形的产生*/

}

 

5.7.3  应用程序

2.  程序清单

#include         <pic.h>

/*此程序实现"看门狗"WDT的功能*/

unsigned         long        I

/*系统初始化子程序*/

void             initial()

{

       OPTION = 0X0F                     /*把前分频器分配给WDT,且分频倍率为1:128*/

       TRISD = 0X00                 /*D口设为输出*/

}

/*延时子程序*/

void        DELAY()

{

 for (i=19999--i)

       continue

}

/*主程序*/

main ()

{

       initial()                             /*初始化,设定看门狗的相关寄存器*/

       PORTD = 0X00                /*D口送00H,发光二极管亮*/

       DELAY()                         /*给予一定时间的延时*/

       PORTD = 0XFF               /*D口送FFH,发光二极管灭*/

while(1)

{

}                                        /*死循环,等待看门狗溢出复位*/

}    

5.8.3  程序清单

   该例在PIC16F877休眠前使8个发光二极管的高4个发光,然后进入休眠工作方式;若按键引起的中断将其激活,则低4个发光。用C语言编写程序时,语句SLEEP()相当于汇编语言中的语句“sleep”,使单片机进入休眠状态。

#include      <pic.h>

/*该程序实现PIC16F877的休眠工作方式,并由实验板上的按键产生"电平变化中断"将其*从休眠状态中激活。休眠与激活的状态由与D口相连的8LED显示。休眠时高4

*LED发光,低4LED熄灭; 激活以后高4LED熄灭,低4LED发光*/

unsigned     long    i

/*系统初始化子程序*/

void initial()

{

                  di()                       /*全局中断禁止,"电平变化中断"只执行唤醒功能*/

                  RBIE=1                 /*PORTB口电平变化中断允许*/

                  RBIF=0                 /*清除B口电平变化中断标志*/

                  TRISB4=1

                  TRISB5=1

                  TRISB2=0

                  TRISB1=0             /*设置与键盘有关的各I/O口的输入输出方式*/

                  TRISD=0X00        /*D口为输出*/

                  PORTB=0X00        /*键盘的行线送低电平,为“电平变化中断” 作准备*/

                  PORTB=PORTB     /*PORTB的值,锁存旧值,也为“电平变化

                                                 *中断”作准备*/

}

/*主程序*/

main ()

{

                  initial()                  /*初始化*/

                  PORTD=0X0F              /*4LED灯亮*/

                  SLEEP()                /*单片机开始进入休眠状态*/

                  PORTD=0XF0              /*激活后,低4LED灯亮*/

while(1)

                  {

                     

                  }

}

文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章: 没有了
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    PIC单片机模拟量输入与输出
    PIC16F877的外围功能模块
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    Copyright © 2005-2008 东方电子科技. All Rights Reserved. 本网站由东方电子科技制作与维护 地址:东莞市塘厦镇林村环村路190号二三楼整层(林村小学对面) 电话:076987282024 手机:13712641904 Email: sanplug@126.com 粤ICP备06051393号 站长:admin