PIC16F877_C语言仿真实例
### PIC16F877 C语言仿真实例解析 #### 一、TMR0计数器仿真实例 **知识点概述:** 此实例利用PIC16F877的TMR0计数器功能,记录外部按键的按压次数,并在中断程序中将次数显示在七段数码管上。当按键次数超过9次后,计数器会重置为0。 **详细解释:** - **硬件配置:** 需要连接按键至单片机的某个I/O引脚,并通过PORTB口连接BCD转7段译码器4511驱动数码管。 - **软件实现:** - 使用Proteus进行电路搭建及仿真。 - 在MPLAB集成开发环境中编写C语言代码,使用HI-TECH的PICC编译器编译。 - 开启TMR0的计数器功能,并设置溢出中断。 - 按键每被按下一次,TMR0就计数一次,当达到设定值时触发中断。 - 在中断服务程序中,将计数值转化为BCD码,再通过4511译码器显示在数码管上。 - **关键代码片段:** ```c #pragma config oscillator=INTOSCIO_NOCLKOUT #pragma config wdt=OFF #pragma config pwr_lvl=PM_ALSWAYS_ON #pragma config brown_out_reset=OFF #pragma config lvp=ON #pragma config code_protect=OFF #pragma config data_protect=OFF #pragma config ee_readprotect=OFF #pragma config ee_crypt=OFF unsigned char TMR0_Count = 0; void main(void) { TRISBbits.TRISB0 = 0; // 设置PORTB.0为输出 T0CONbits.T0CS = 0; // 设置TMR0为内部时钟源 T0CONbits.T0SE = 0; // 不使用TMR0预分频器 T0CONbits.T0PS = 0b000; // 设置TMR0预分频为1:1 INTCONbits.T0IF = 0; // 清除TMR0中断标志 INTCONbits.T0IE = 1; // 允许TMR0中断 INTCONbits.GIE = 1; // 全局中断允许 TRISBbits.TRISB4 = 1; // 设置PORTB.4为输入 (假设按键连接于此) while(1) { if(PORTBbits.RB4 == 0) // 检测按键是否按下 { __delay_us(20); // 去抖动 if(PORTBbits.RB4 == 0) { TMR0 = 0; // 重置TMR0 INTCONbits.T0IF = 0; // 清除中断标志 } } } } void TMR0_ISR(void) { if(INTCONbits.T0IF == 1) { TMR0_Count++; // 计数器增加 if(TMR0_Count > 9) TMR0_Count = 0; // 超过9次则重置 // 将TMR0_Count转化为BCD码并显示在数码管上 INTCONbits.T0IF = 0; // 清除中断标志 } } ``` #### 二、TMR1定时器仿真实例 **知识点概述:** 此实例原计划利用TMR1定时器实现类似实时时钟的功能,但由于外部32.768kHz晶振无法正常工作,最终改为使用内部时钟实现毫秒和秒数的计时,并显示在两个七段数码管上。 **详细解释:** - **问题分析:** 外部晶振不起振可能是由于晶振本身故障或电路设计不合理导致。 - **替代方案:** - 修改程序以使用内部时钟源。 - 设置TMR1定时器预分频器,以实现毫秒级计时。 - 在主循环中更新数码管显示,分别显示毫秒和秒数。 - **关键代码片段:** ```c #pragma config oscillator=INTOSCIO_NOCLKOUT #pragma config wdt=OFF #pragma config pwr_lvl=PM_ALSWAYS_ON #pragma config brown_out_reset=OFF #pragma config lvp=ON #pragma config code_protect=OFF #pragma config data_protect=OFF #pragma config ee_readprotect=OFF #pragma config ee_crypt=OFF unsigned char millisecond = 0; unsigned char second = 0; void main(void) { TRISBbits.TRISB0 = 0; // 设置PORTB.0为毫秒显示输出 TRISBbits.TRISB1 = 0; // 设置PORTB.1为秒显示输出 T1CONbits.T1CS = 1; // 设置TMR1为内部时钟源 T1CONbits.T1CKPS1 = 1; // 设置TMR1预分频为1:32 T1CONbits.T1CKPS0 = 1; // 设置TMR1预分频为1:32 INTCONbits.T0IE = 1; // 允许TMR1中断 INTCONbits.GIE = 1; // 全局中断允许 while(1) { // 更新数码管显示 PORTBbits.RB0 = (millisecond / 10) % 10; // 显示毫秒的十位 PORTBbits.RB1 = millisecond % 10; // 显示毫秒的个位 millisecond++; // 毫秒计数器递增 if(millisecond >= 100) { millisecond = 0; second++; // 秒计数器递增 if(second >= 10) { second = 0; // 秒计数器超过9后重置 } } } } ``` #### 三、TMR2中断产生方波 **知识点概述:** 此实例通过TMR2定时器的中断功能,在RB0口产生并输出一个周期为32ms的方波。 **详细解释:** - **硬件配置:** 需要在RB0口连接示波器观察波形。 - **软件实现:** - 设置TMR2定时器预分频器以获得合适的定时周期。 - 在中断服务程序中改变RB0的状态,实现方波的输出。 - 在主循环中初始化TMR2定时器和中断。 - **关键代码片段:** ```c #pragma config oscillator=INTOSCIO_NOCLKOUT #pragma config wdt=OFF #pragma config pwr_LVL=PM_ALSWAYS_ON #pragma config brown_out_reset=OFF #pragma config lvp=ON #pragma config code_protect=OFF #pragma config data_protect=OFF #pragma config ee_readprotect=OFF #pragma config ee_crypt=OFF void main(void) { TRISBbits.TRISB0 = 0; // 设置PORTB.0为输出 T2CONbits.T2CKPS1 = 1; // 设置TMR2预分频为1:16 T2CONbits.T2CKPS0 = 0; // 设置TMR2预分频为1:16 PR2 = 124; // 设置TMR2的重载寄存器,以得到16ms的周期 INTCON2bits.TMR2IE = 1; // 允许TMR2中断 INTCONbits.GIE = 1; // 全局中断允许 while(1) { // 主循环无需执行任何操作 } } void TMR2_ISR(void) { PORTBbits.RB0 = !PORTBbits.RB0; // 反转RB0状态 } ``` 以上实例涵盖了PIC16F877单片机的基本定时器、计数器功能及其在实际项目中的应用。通过这些实例的学习,可以深入了解和掌握单片机定时器的工作原理以及如何通过软件控制实现特定功能。
- hushui2012-08-11很好 MICCC可以编译通过
- guogongyou2013-02-03很详细清楚
- 粉丝: 0
- 资源: 5
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助