PIC单片机RB口中断程序设计
PIC单片机24C512程序范本
![PIC单片机24C512程序范本](https://img.taocdn.com/s3/m/d44f4ce60d22590102020740be1e650e52eacf24.png)
PIC单片机24C512程序范本/********************* PIC16F886 读写AT24C512 *********************/#include__CONFIG(XT&WDTDIS); //定义配置字,晶振类型:XT,关闭看门狗#define sda RC4 //EEPROM SDA接RC4#define scl RC3 //EEPROM SCL接RC3#define RSPIN RA0 //LCD 1602 RS接RA0#define RWPIN RA1 //LCD 1602 R/W接RA1#define EPIN RA2 //LCD 1602 E接RA3bit eepromdi;bit eepromdo;//---------------------------------------// 非精确延时函数//-----------------------------------------void delay(unsigned int t){unsigned int i,j;for(i=0;i<t;i++){for(j=0;j<10;j++){asm("CLRWDT"); //必须要加喂狗指令,否则到这里就会复位}}//---------------------------------------// 1602忙检测函数//-----------------------------------------void lcd_wait_busy(void){TRISB7=1;RSPIN=0;RWPIN=1;EPIN=1;// while(RB7==1); //读忙状态,不忙时退出。
proteus仿真时不能检测1602的忙信号,用延时替代delay(7);EPIN=0;TRISB7=0;}//---------------------------------------// 1602写命令函数//-----------------------------------------void lcd_write_com(unsigned char combuf){RSPIN=0;RWPIN=0;PORTB=combuf;EPIN=1;asm("NOP"); //空操作,延时一个指令周期EPIN=0;//---------------------------------------// 1602写命令函数(带忙检测)//-----------------------------------------void lcd_write_com_busy(unsigned char combuf){lcd_wait_busy();lcd_write_com(combuf);}//---------------------------------------// 1602写数据函数(带忙检测)//-----------------------------------------void lcd_write_data(unsigned char databuf){lcd_wait_busy();RSPIN=1;RWPIN=0;PORTB=databuf;EPIN=1;asm("NOP");EPIN=0;}//---------------------------------------// 1602显示地址写函数//-----------------------------------------void lcd_write_address(unsigned char x,unsigned char y) {x&=0x0f;y&=0x01;if(y==0x00)lcd_write_com_busy(x|0x80);elselcd_write_com_busy((x+0x40)|0x80);}//---------------------------------------// 1602初始化函数//-----------------------------------------void lcdreset(void){delay(150);lcd_write_com(0x38);delay(50);lcd_write_com(0x38);delay(50);lcd_write_com(0x38);lcd_write_com_busy(0x38);lcd_write_com_busy(0x08);lcd_write_com_busy(0x01);lcd_write_com_busy(0x06);lcd_write_com_busy(0x0c);}//---</t;i++)------------------------------------// 指定地址写入函数//-----------------------------------------void lcd_write_char(unsigned char x,unsigned char y,unsigned char buf){lcd_write_address(x,y);lcd_write_data(buf);}//--------------------------------------- // 延时函数//----------------------------------------- void delay1(void){unsigned char k;for(k=0;k<180;k++)asm("CLRWDT");}//--------------------------------------- // 启动I2C总线函数//----------------------------------------- void i2cstart(void){scl=1;asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");sda=1;delay1();sda=0;delay1();scl=0;delay1();}//--------------------------------------- // 终止I2C总线函数//----------------------------------------- void i2cstop(void){sda=0;sda=0;asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");scl=1;delay1();sda=1;delay1();scl=0;delay1();}//--------------------------------------- // 从I2C总线读入一位数据函数//----------------------------------------- void bitin(void){eepromdi=1;TRISC4=1;scl=1;asm("NOP");asm("NOP");asm("NOP");asm("NOP");eepromdi=sda;asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");scl=0;asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");TRISC4=0;}//--------------------------------------- // 向I2C总线写入一位数据函数//----------------------------------------- void bitout(void){sda=eepromdo;asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");scl=1;asm("NOP");asm("NOP");asm("NOP");asm("NOP");scl=0;asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");}//--------------------------------------- // 向I2C总线写入一字节函数//----------------------------------------- void i2cwrite(unsigned char sedata) {unsigned char k;for(k=0;k<8;k++){if(sedata&0x80){eepromdo=1;}else{eepromdo=0;}sedata=sedata<<1;bitout();}bitin();}//---------------------------------------// 从I2C总线读出一字节函数//----------------------------------------- unsigned char i2cread(void){unsigned char redata;unsigned char m;for(m=0;m<8;m++){redata=redata<<1;bitin();if(eepromdi==1){redata|=0x01;}else{redata&=0xfe;}asm("NOP");}eepromdo=1;bitout();return redata;}//---------------------------------------// 从AT24C64指定地址上读出1字节数据函数//----------------------------------------- unsigned char read_24C64(unsigned int address){unsigned char eebuf3;i2cstart();i2cwrite(0xa0);i2cwrite(address>>8);i2cwrite(address%256);i2cstart();i2cwrite(0xa1);eebuf3=i2cread();i2cstop();return eebuf3;}//---------------------------------------// 向AT24C64指定地址上写入1字节数据函数//-----------------------------------------void write_24C64(unsigned int address1,unsigned char byte) {i2cstart();i2cwrite(0xa0);i2cwrite(address1>>8);i2cwrite(address1%256);i2cwrite(byte);i2cstop();}//---------------------------------------// 初始化端口函数//-----------------------------------------void init(void){ANSEL=0X00; //所有IO为数字IOANSELH=0X00; //所有IO为数字IOOSCCON=0X08; //系统时钟由CONFIG决定TRISA=0B11111000; //RA1,RA2,RA3置为输出,其他置为输入TRISB=0B00000000; //RB0-RB7置为输出1TRISC=0B11100111; //RC3,RC4为输出,其他置为输入RBIE=0; //RB口电平变化中断禁止}//---------------------------------------// 主函数//-----------------------------------------void main(void){unsigned char data,buf;unsigned int a;init();lcdreset(); //复位1602lcd_write_char(0,0,'a');lcd_write_char(1,0,'d');lcd_write_char(2,0,'d');lcd_write_char(3,0,'r');lcd_write_char(4,0,'e');lcd_write_char(5,0,'s');lcd_write_char(6,0,'s');lcd_write_char(8,0,'|');lcd_write_char(10,0,'W');lcd_write_char(8,1,'|');lcd_write_char(10,1,'R');while(1){for(a=0;a<65535;a=a+64){data=rand(); //产生随机数据lcd_write_char(0,1,a/10000+0x30);lcd_write_char(1,1,(a%10000)/1000+0x30); lcd_write_char(2,1,(a%1000)/100+0x30); lcd_write_char(3,1,(a%100)/10+0x30);lcd_write_char(4,1,a%10+0x30);write_24C64(a,data); //写数据lcd_write_char(12,0,data/100+0x30);lcd_write_char(13,0,(data%100)/10+0x30); lcd_write_char(14,0,data%10+0x30);buf=read_24C64(a); //读数据lcd_write_char(12,1,data/100+0x30);lcd_write_char(13,1,(data%100)/10+0x30); lcd_write_char(14,1,data%10+0x30);delay(3000);}}}。
pic单片机C语言程序例程之wakeup
![pic单片机C语言程序例程之wakeup](https://img.taocdn.com/s3/m/7739c3611ed9ad51f01df212.png)
/*该程序实现PIC18F458的休眠工作方式,并由实验板上的按键产生"电平变化中断"将其从休眠状态中激活。
休眠与激活的状态由与D口相连的8个LED显示。
休眠时高4个
LED发光,低4个LED熄灭; 激活以后高4个LED熄灭,低4个LED发光*/
#include "p18f458.h"
unsigned long i;
/*系统初始化子程序*/
void initial()
{
INTCON=0x08; /*全局中断禁止,"电平变化中断"只执行唤醒功能*/
/*清除B口电平变化中断标志*/
TRISA=0x00; /*A口设置为输出*/
TRISB=0XF0; /*RB1输出,RB4输入*/
TRISD=0X00; /*D口为输出*/
TRISE=0x00; /*E口设置为输出*/
PORTBbits.RB1=0;
PORTAbits.RA3=0;
PORTE=0; /*将K1,K2,K3,K4四条列线置0*/
PORTB=PORTB; /*读PORTB的值,锁存旧值,也为“电平变化
中断”作准备*/
}
void SLEEP()
{
_asm
SLEEP /*进入休眠状态*/
_endasm
}
/*主程序*/
main ()
{
initial(); /*初始化*/
PORTD=0X0F; /*高4个LED灯亮*/
SLEEP(); /*单片机开始进入休眠状态*/
PORTD=0XF0; /*激活后,低4个LED灯亮*/
while(1)
{
;
}
}。
单片机中断的流程
![单片机中断的流程](https://img.taocdn.com/s3/m/c24b1f9459f5f61fb7360b4c2e3f5727a5e924a4.png)
单片机中断的流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor. I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!单片机中断的流程一、中断初始化阶段。
在使用单片机的中断功能之前,需要进行一系列的初始化工作。
PIC单片机中断系统详细汇总
![PIC单片机中断系统详细汇总](https://img.taocdn.com/s3/m/21bb1880ab00b52acfc789eb172ded630b1c98ed.png)
随着物联网、人工智能等技术的发展,中断系统与其他系 统的融合成为未来的发展方向。
在物联网和人工智能应用中,设备需要实时响应各种事件 ,如传感器数据变化、网络数据包到达等。因此,将中断 系统与操作系统、网络协议栈等其他系统进行融合,可以 实现更高效的事件处理和资源调度,提高系统的实时性和 可靠性。
串行通信中断的配置
需要设置串行通信的波特率、数据位、停止位、奇偶 校验等参数,以及中断触发方式。
串行通信中断的应用
在RS-232、RS-485、SPI等串行通信协议中广泛应 用。
外部事件中断
外部事件中断
01
用于实现外部事件触发中断,例如按键按下、传感器触发等。
外部事件中断的配置
02
需要设置外部事件的检测方式、触发条件以及中断处理程序。
中断的作用:提高CPU的效率,实现对外部事件的实时响应 和处理。
PIC单片机的中断源
外中断
由外部硬件设备产生的中断,例如定 时器溢出、串口接收数据等。
内中断
由单片机内部硬件产生的中断,例如 比较器匹配、捕获比较器等。
中断优先级和向量
中断优先级
用于标识不同中断的优先级,优先级高的中断会优先得到处理。
中断处理程序执行
一旦PIC单片机响应中断,它会跳转 到相应的中断向量表地址,执行中断 处理程序。
中断返回和清除
中断返回
中断处理程序执行完毕后,PIC单片机会自动返回到被中断的程序继续执行。
中断清除
某些中断源在响应后会自行清除中断标志位,而有些则需要手动清除。
03
PIC单片机中断系统的应用
定时器中断
中断处理程序应遵循一定的编写规范,以确 保程序正确、稳定地运行。例如,应避免在 中断处理程序中进行耗时的操作,以减小对 系统性能的影响。
pic 中断程序实例
![pic 中断程序实例](https://img.taocdn.com/s3/m/e0bd9b88f021dd36a32d7375a417866fb84ac081.png)
pic 中断程序实例
下面是一个简单的中断程序实例:
#include <avr/io.h>
#include <avr/interrupt.h>
volatile int count = 0;
ISR(TIMER0_COMPA_vect) 定时器0比较匹配中断
{
count++;
}
int main(void)
{
初始化定时器0和比较匹配值
OCR0A = 255; 设置比较匹配值
TCCR0A = (1 << WGM01); CTC模式
TCCR0B = ((1 << CS00) (1 << CS02)); 分频器1024 TIMSK0 = (1 << OCIE0A); 打开比较匹配中断
sei(); 开启中断
while(1)
{
if(count > 1000) 如果计数超过1000
{
执行你想要做的操作
count = 0; 清零计数器
}
}
}
这个程序使用定时器0的比较匹配中断来计数,每次中断发生时,计数器就会加1。
在主循环中,如果计数器超过了1000,程序就会执行一些操作,并且将计数器清零。
要使这个程序工作,你需要连接一个LED或者其他的输出设备到Arduino板的一个数字引脚上,并在中断发生时将其输出高电平。
你还需要调整比较匹配值和分频器以控制中断的频率。
pic单片机中断
![pic单片机中断](https://img.taocdn.com/s3/m/0fefa197a0116c175f0e484a.png)
PIC18系列的低优先级中断入口地址在0x0018地址,下面的代码是在入口地址处放置一个向量函数,这个向量函数里就是一个内嵌汇编的GOTO指令,GOTO到低优先级的中断服务函数InterruptHandlerLow。
//----------------------------低优先级中断入口-----------------------------------1#pragma code InterruptVectorLow = 0x18 //用#pragma伪指令定义一个名字叫InterruptVectorLow的段,并把这个段放到0x18地址起始的代码空间2void InterruptVectorLow (void) //低优先级中断向量函数3 {4_asm5goto InterruptHandlerLow //内嵌汇编指令6_endasm7 }8#pragma code //这里不是多余的,它是告诉连接器回到默认的代码段,如果不加的话,连接器就会傻傻地把后面的代码紧跟着上面的代码一直放下去。
而LKR文件里定义了向量区最多到0x29地址,所以如果没加此行通常会报错910#pragma interruptlow InterruptHandlerLow //这里使用interruptlow这个关键词来声明InterruptHandlerLow这个函数是低优先级中断服务函数,用了关键词后,这个函数将会由编译器自动产生基本的现场保护,并且这个函数的返回将是使用RETFIE 返回的。
111213void InterruptHandlerLow (void)14 {15/* 低优先级服务函数的代码写在这里*/16 }PIC18系列的高优先级中断入口地址在0x0008地址,下面的代码是在这个入口地址处放置一个向量函数,这个向量函数里就是一个内嵌汇编的GOTO指令,GOTO到高优先级的中断服务函数InterruptHandlerHigh 。
第三章 PIC16F887功能及编程
![第三章 PIC16F887功能及编程](https://img.taocdn.com/s3/m/6076ef8483d049649b66586d.png)
0:计时
01-1:4
… 1111-1:16
1X-1:16
福州大学电气工程与自动化学院
• TMR0是个8位计数/定时器,有可编程预分频率 器,可对外部脉冲计数或对内部指令脉冲计数的 功能。
• 当对外部脉冲计数时,符合一定要求的外部脉冲 送到RA4/T0CKI,且OPTION_REG(<T0CS>)要 置1,且该口(RA4)要设置为输入。
• TMR0寄存器的地址在01H、101H。 • TMR0有溢出中断功能。
中断 信接收 信发送 行通信 模块 溢出 溢出 使能 中断 中断 中断 中断 中断 中断
使能 使能 使能 使能 使能 使能
福州大学电气工程与自动化学院
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
- ADIF RCIF TXTF SSPIF CCP1IF TMR2IF TMR1IF - AD转换 串行通 串行通 同步串 CCP1 TMR2 TMR1
• 恢复被保护的相关寄存器 • 程序执行到”RETFIE”时后入先出的原则,从堆栈
中弹出地址给PC,GIE=1,程序返回到中断前 要执行的程序,程序恢复中断前程序的运行状 态。
福州大学电气工程与自动化学院
PIC16F887有17个中断源,每个中断源都有自 己的使能控制位(IE)和中断标志位(IF)。包括:
• 假设当前TRM1H、TMR1L=0x01FF,则在读取TMR1时 就可能发生错误:
• 如先读低字节,得到0xFF,假设此时发生进位,则再读 高字节时得到0x02,总的结果是0x2FF,显然是错误的。
• 如先读高字节,得到0x01,假设此时发生进位,则再读低 字节得到0x00,总的结果是0x100,也是错误的。
PIC单片机中断系统详细汇总
![PIC单片机中断系统详细汇总](https://img.taocdn.com/s3/m/c5fc1aa7852458fb760b5617.png)
精选版课件ppt
9
§8.4 中断相关的寄存器
与中断有关的特殊功能寄存器SFR共有6个, 分别是:
选 项 寄 存 器 OPTION_REG 、 中 断 控 制 寄 存 器INTCON、第一外围设备中断标志寄存器PIR1、 第一外围设备中断屏蔽寄存器PIE1(也称中断使能 寄存器)、第二外围设备中断标志寄存器PIR2和第 二外围设备中断屏蔽寄存器PIE2,如表9.2所列。
1=选择RB0/INT上升沿触发;
精选版课件ppt
12
0=选择RB0/INT下降沿触发 ⒉中断控制寄存器INTCON
中断控制寄存器是一个可读/可写的寄存 器,各位的分布形式如下:
它将第一梯队中的3个中断源的标志位和屏 蔽位,以及PEIE和GIE包含在其中:
RBIF : 端 口 RB 的 引 脚 RB4 ~ RB7 电 平 变 化 中 断标志位。
TMR2IF:定时/计数器TMR2模块溢出中断标 志位。
➢ 1=发生了TMR2溢出; 0=未发生TMR2溢出。
CCP1IF:输入捕捉/输出比较/脉宽调制CCP1 模块中断标志位。
❖ 输入捕捉模式下:
1=发生了捕捉中断请求;
0=未发生捕捉中断请求。
精选版课件ppt
17
❖ 输出比较模式下: 1=发生了比较输出中断请求; 0=未发生比较输出中断请求。
后5个SFR,共有40位,但仅使用了30位来控 制中断,分别与图9.l中的中断逻辑电路的输入信 号成严格的对应关系。
精选版课件ppt
10
精选版课件ppt
11
⒈选项寄存器OPTION _REG
OPTION_REG选项寄存器是可读写的, 各位的分布形式:
该寄存器包含了与定时/计数器TMR0、 分频器和端口RB有关的控制位。RB端口引脚 RB0和外部中断INT复用一脚,与该脚有关的一 个控制位含义如下: INTEDG:外部中断INT触发信号边沿选择位:
单片机 外部中断 程序设计
![单片机 外部中断 程序设计](https://img.taocdn.com/s3/m/c99fa9cd690203d8ce2f0066f5335a8102d266ed.png)
单片机外部中断程序设计一、引言在单片机应用系统中,外部中断是一个非常重要的功能。
当外部事件发生时,中断系统可以打断正在执行的程序,转而执行相应的中断服务程序(ISR)。
本指南将详细介绍如何进行单片机外部中断的程序设计,主要包括以下五个方面:配置中断控制器、定义中断服务程序、设置中断触发方式、开启外部中断以及测试与调试。
二、配置中断控制器中断控制器是单片机的核心部件之一,它负责管理中断的优先级、触发方式以及处理方式。
在进行外部中断程序设计之前,需要先配置中断控制器。
根据所使用的单片机型号和中断控制器的不同,配置方法会有所差异。
一般情况下,需要设置以下几个参数:1.中断触发方式:电平触发或边沿触发。
2.中断优先级:多个中断源的情况下,需要确定每个中断源的优先级。
3.中断处理方式:通常有向量中断和非向量中断两种处理方式,需要根据具体硬件平台进行选择。
三、定义中断服务程序中断服务程序(ISR)是当外部中断触发时,单片机执行的一段程序代码。
在定义ISR时,需要注意以下几点:1.ISR的入口和出口参数:一般情况下,单片机厂商会提供相应的库函数,用于定义ISR的入口和出口参数。
2.ISR的执行时间:为了保证系统的实时性,ISR的执行时间应尽可能短,避免长时间的操作导致系统响应延迟。
3.ISR的返回值:根据需要,ISR可以返回一定的状态信息或处理结果。
四、设置中断触发方式根据具体应用需求,需要设置外部中断的触发方式。
常见的触发方式包括电平触发和边沿触发。
电平触发是指当外部信号电平发生变化时,触发中断请求;边沿触发则是在信号电平由低变高或由高变低时触发中断请求。
选择合适的触发方式可以提高系统的响应速度和准确性。
五、开启外部中断完成以上步骤后,最后一步是开启外部中断。
具体方法取决于所使用的单片机型号和编译器。
一般来说,需要使用相应的指令或函数来开启外部中断。
在开启外部中断时,需要注意以下几点:1.中断使能:需要开启单片机的中断使能开关。
《PIC16系列单片机C程序设计与proteus仿真》学习之1----RB0_INT中断编程
![《PIC16系列单片机C程序设计与proteus仿真》学习之1----RB0_INT中断编程](https://img.taocdn.com/s3/m/b59b576a1eb91a37f1115cda.png)
《PIC16系列单片机C程序设计与proteus仿真》学习之一----RB0/INT中断编程//用RB0/INT按键,每按一下,LED翻转亮,晶振4MHZ#include<pic.h>//#include<pic16f8xx.h>__CONFIG(0x3f71);//配置为设定:XT,WDT,off等#define LED RB1 //所有有LED字符的地址实际上是RB1char A; //全局变量,保存LED的状态void DELAY(unsigned int);void interrupt ISR(void);void main(){OPTION=0b00000000; //B口弱上拉,RB0为下降沿触发中断TRISB =0b00000001;//设定RB0为输入,RB1为输出(置1为输入,置0为输出)INTCON=0B10010000; //允许RB/INT中断LED=1; //RB1=1,先让LED灯亮A=1;while(1); //原地等待中断}//-------delay n msvoid DELAY(unsigned int n){unsigned int j;char k;for(j=0;j<n;j++)for(k=246;k>0;k--) NOP();}//----interrupt isrvoid interrupt ISR(void){if(INTF==1)//如果是INT中断才执行以下程序{DELAY(30);//先延时消抖INTF=0; //消抖后才将INT中断标志清零if(A==1){A=0;LED=0;}else{A=1;LED=1;}}}-------------------------------------------------PROTEUS如下:PS:详情请参考《PIC系列单片机设计与PROTEUS仿真》一书P114。
PIC实验报告(中断、定时、PWM、AD程序代码)
![PIC实验报告(中断、定时、PWM、AD程序代码)](https://img.taocdn.com/s3/m/b937fe6ea98271fe910ef941.png)
实验一:定时器1. 实验目的:利用定时器0,定时器1,定时2实现4盏流水灯2. 实验内容 a,程序框图定时器0:/************************************************** 计算公式:(256-X)*K*T=25 000us,定时器延时25ms,预分频为K 为64,利用软件编程实现1s 脉冲输出,RB0作为输出 ************************************************/ #include<pic.h>__CONFIG(0x20F1); __CONFIG(0x3F71); #define T0_25MS 61 char a=0;void interrupt ISR() {if(T0IF==1)定时器1定时500MS定时器0定时50MS 、定时器1定时器2定时50MS时间到? 时间到? 时间到?a 的值加1 led 灯循环左移一位 a 的值加1a=20?a=10?a=0,led 灯循环左移一位 a=0,led 灯循环左移一位开始开始开始T0IF=0;TMR0=T0_25MS;a++;if(a==20) //输出1s脉冲{PORTD=(PORTD<<1);a=0;if(PORTD==0x10)PORTD=0x01;}}}void timer0init(){OPTION=0b10000110; //,预分频器给TMR0,TMR0预分频系数为1:64 INTCON=0b10100000; //GIE,PEIE置1}void main(){timer0init();TRISD=0;PORTD=0x01;while(1);}定时器1:/**************************************************计算公式:(65536-X)*K*T=500 000us,定时器延时500ms,预分频为8,利用软件编程实现1s脉冲输出,RB0作为输出************************************************/#include<pic.h>__CONFIG(0x20F1);__CONFIG(0x3F71);#define T1_500MS 3036void interrupt ISR(){if(TMR1IF==1){TMR1IF=0;TMR1H=T1_500MS>>8;TMR1L=T1_500MS;PORTD=(PORTD<<1);if(PORTD==0x10)PORTD=0x01;}void timer1init(){TMR1H=T1_500MS>>8;TMR1L=T1_500MS;TMR1IE=1;INTCON=0b11000000; //GIE,PEIE置1T1CON=0b00110001;; //TMR1预分频系数为1:8}void main(){timer1init();TRISD=0;PORTD=0x01;while(1);}定时器2:/**************************************************计算公式:(PR2+1)*K1*K2*T=50 000us,定时器延时50ms,预分频为K1为16,后分频器K2为15利用软件编程实现1s脉冲输出,RB0作为输出************************************************/#include<pic.h>__CONFIG(0x20F1);__CONFIG(0x3F71);#define LED RB0char a=0;void interrupt ISR(){if(TMR2IF==1){TMR2IF=0;a++;if(a==10) //1秒到了{PORTD=(PORTD<<1);a=0;if(PORTD==0x10)PORTD=0x01;}}}void timer2init()TMR2IE=1;PR2=207;INTCON=0b11000000; //GIE,PEIE置1T2CON=0B001110111; //TMR2预分频系数为1:16,后分频器为1:15 }void main(){timer2init();TRISD=0;PORTD=0x01;while(1);}实验二:RB0中断1.实验目的:a.利用外部中断RB0实现流水灯左移2.程序框图:开始RB0按下?进入中断,led灯循环左移一位程序:#include<pic.h>__CONFIG(0x20F1);__CONFIG(0x3f71);void delaynms(unsigned int n);void interrupt ISR(void);void main(){OPTION=0b00000000;ANS12=0;WPUB0=1;TRISB=0b00000001;INTCON=0b10010000;TRISD=0b00000000;PORTD=0x01;while(1);}void interrupt ISR(void){if(INTF==1){delaynms(30);INTF=0;PORTD=(PORTD<<1);if(PORTD==0x10)PORTD=0x01;}}void delaynms(unsigned int n){unsigned int j;char k;for(j=0;j<n;j++)for(k=246;k>0;k--)NOP();}实验三:AD转换1.实验目的:利用PIC内部AD转换器,AN0通道口采集模拟数据,通过LCD1602显示结果2.程序框图:程序:#include<pic.h>__CONFIG(0x3F39); __CONFIG(0x20F1); #define RS RD4 #define RW RD5 #define E RD6#define uint unsigned int char QW,BW,SW,GW;//8段共阳LED 显示代码,0位-7位分别控制a -h 段const char LED_CODE[]={0b11000000, 0b11111001,0b10100100,0b10110000,0b10011001, 0b10010010,0b10000010,0b11111000,0b10000000,0b10010000,0b01111111}; uint AD_SUB(char k);void init1602(); //1602初始化 void write_com(char com);//写指令 void write_date(char data);//写数据 void delaynms(unsigned int n); void spiinit();void SPI_WRITE(char ); void displayled(); void display1602(); void BCD(uint R1); void main() {uint y;TRISA=0b00000001;选择AD 通道启动ADGODON E=0?数据送1602显示初始化数据送数码管显示 开始ANSEL=0b11111111; //AN0~AN7为模拟输入,上电默认,可不设TRISD=0; //D口设置为输出PORTD=0;spiinit();init1602();while(1){y=AD_SUB(0); //0表示第0个通道BCD(y);displayled();display1602();delaynms(500); //此不不能忽略}}void BCD(uint R1){QW=0;BW=0;SW=0;GW=0;while(R1>=1000){R1-=1000;QW++;}while(R1>=100){R1-=100;BW++;}while(R1>=10){R1-=10;SW++;}GW=R1;}void displayled(){SPI_WRITE(GW); //先发个位SPI_WRITE(SW); //发十位SPI_WRITE(BW); //发百位SPI_WRITE(10); //发小数点SPI_WRITE(QW); //发千位}void display1602(){write_com(0x80);write_date(0x30+QW);write_date(0x2e); //小数点write_date(0x30+BW);write_date(0x30+SW);write_date(0x30+GW);write_date(0x56); //"V"}void SPI_WRITE(char b){char BUF;BUF=LED_CODE[b];SSPBUF=BUF; //发出数据while(BF==0);BUF=SSPBUF;}void spiinit(){TRISC=0b00010000;SSPEN=1;CKP=1;SSPM3=0;SSPM2=0;SSPM1=0;SSPM0=1;SMP=1;CKE=0;}uint AD_SUB(char k){char i;uint temp;float x;ADCON0=0b01000001; //TAD=8TOSC,ADFM=1; //设置成右对齐ADCON0|=(k<<4);for(i=1;i<5;i++)NOP(); //打开AD通道后延时20us左右GODONE=1; //开始AD转换while(GODONE==1); //等待转换完成ADIF=0;temp=ADRESH<<8;temp|=ADRESL;x=temp/1023.0*5.0;temp=x*1000;return(temp);}void init1602(){delaynms(20); //延时时间大于15mswrite_com(0x03);delaynms(5);write_com(0x03);delaynms(5);write_com(0x03);delaynms(5);write_com(0x02); //归HOME位,此不不可少delaynms(5);write_com(0x28); //工作方式设置,4位数据线,2行字符,5*7字体write_com(0x0c); //显示开关设置,画面开,光标消失,禁止闪烁write_com(0x06); //输入方式设置,AC为加一计数器write_com(0x01); //清屏write_com(0x80); //开始显示位置delaynms(2);}void write_com(char com){RS=0; //写指令RW=0;PORTD&=0xf0; //低四位清0E=1; //有效发送PORTD|=((com>>4)&0x0f);//先发高四位delaynms(5);E=0;PORTD&=0xf0;E=1;PORTD|=(com&0x0f);//再发低四位delaynms(5);E=0;}void write_date(char data){RS=1; //写数据RW=0;PORTD&=0xf0;E=1;PORTD|=((data>>4)&0x0f);//先发高四位delaynms(5);E=0;PORTD&=0xf0;E=1;PORTD|=(data&0x0f); //再发低四位delaynms(5);E=0;RS=0;}void delaynms(unsigned int n){unsigned int j;char k;for(j=0;j<n;j++)for(k=246;k>0;k--)NOP();}实验四:PWM1.实验目的:通过PIC单片机输出PWM不同占空比脉冲波形2.程序流程:程序:#include<pic.h>__CONFIG(0x3f3a);char a;void CSH();void interrupt ISR(void);void delaynms(unsigned int n); void main(){CSH();while(1){if(a==0)开始初始化占空比为0.1RB0是否按下进入中断,a加1a=1,则输出占空比0.1 a=2,则输出占空比0.3a=3,则输出占空比0.6a=4,则输出占空比0.9a=5,则a清0,占空比为0.1CSH();}}void CSH(){TRISC2=0;TRISD=0;PR2=249;CCPR1L=0x32;CCP1CON=0x0c;T2CON=0x05;OPTION=0b00000000;ANS12=0;WPUB0=1;TRISB=0b00000001;INTCON=0b10010000;}void interrupt ISR(void){if(INTF==1){delaynms(30);if(RB0==0){INTF=0;a++;switch(a){case 1:CCPR1L=0x19;PR2=249;CCP1CON=0x0c;T2CON=0x05;break; //占空比0.1 case 2:CCPR1L=0x4b;PR2=249;CCP1CON=0x0c;T2CON=0x05;break; //占空比0.3 case 3:CCPR1L=0x96;PR2=249;CCP1CON=0x0c;T2CON=0x05;break; //占空比0.6 case 4:CCPR1L=0xe1;PR2=249;CCP1CON=0x0c;T2CON=0x05;break;// 占空比0.9 case5:a=0;break;}}}}void delaynms(unsigned int n){unsigned int j;char k;for(j=0;j<n;j++)for(k=246;k>0;k--)NOP();}。
PIC单片机的中断程序
![PIC单片机的中断程序](https://img.taocdn.com/s3/m/08d2fe2b58fafab068dc0214.png)
PIC单片机的中断程序PIC 单片机的中断程序中断是 PIC 高手必须掌握的武器,转贴一篇,还希望大家补充发表对中断应用的见解。
与 51 或者其他系列的单片机相比,PIC 单片机的中断机制有其特殊之处,针对我们一些初学者存在的一些问题和疑惑,我在此做一个个人总结,不当的地方,请站友们指正。
先摘引三个对 PIC 中断理解的回帖,然后我再对中断活动的过程、应该注意的事项、及一个疑惑进行较详细的总结和解释。
--------------- john frank :关于 pic 中断有些不明白的地方借用大虾的程序中断服务代码 btfss INTCONT0IE 判断是否为 T0 中断 goto other_int btfssINTCONT0IF it ?s the time of T0 int goto other_int bcf INTCONT0IF 是T0 中断清除中断标志 movlw 0x10 微秒的高位字节加上定时时间 256x16 分频40960x1000 的高位0x10addwf us1goto end_intother_int 可添加其他中断服务代码nop other isr code can be added end_int 恢复现场假如又有新的中断正好在这段程序中间产生 btfss INTCONT0IFgoto other_intbcf INTCONT0IF 程序岂不是要出错跑飞了 john frank:谢谢你的关注。
我讲一下自己的理解,权做回答,不当之处,还请站友们指点。
pic 中档单片机系列没有“硬件中断优先级别”(请允许我这样说),含义是指:当内核正在处理当前的中断服务 A 时,在这个期间里,其他任何中断的产生,只能使其标志位 xxIF 置 1,不能剥夺当前中断服务对CPU 的占用权(反应在 PC 指针不能被新的中断改变指向),必须等到当前中断服务处理 A 完毕,然后,根据 goto other_int 语句的转向,依次判断。
pic单片机串口中断写法
![pic单片机串口中断写法](https://img.taocdn.com/s3/m/844c9c850d22590102020740be1e650e52eacfc3.png)
pic单片机串口中断写法在PIC单片机中,串口中断的写法通常涉及到以下几个步骤:1. 配置串口:首先,你需要配置PIC单片机的串口模块。
这包括设置波特率、数据位、停止位等参数。
2. 配置中断:接下来,你需要配置PIC单片机的中断模块。
你需要设置中断触发方式(上升沿、下降沿或电平变化),并启用串口中断。
3. 编写中断服务程序:最后,你需要编写串口中断服务程序。
当串口接收到数据或发送数据完成时,将触发中断。
在中断服务程序中,你可以执行相应的操作,例如读取接收到的数据或发送数据。
下面是一个简单的例子,展示了如何编写PIC单片机的串口中断服务程序:```cinclude <>define _XTAL_FREQ // 定义振荡器频率为4MHzvoid main(void)// 配置振荡器OSCICN = 0b; // 设置振荡器频率为4MHz// 配置串口SPBRG = 0x18; // 设置波特率为9600,根据需要调整TXSTA = 0b; // 设置数据位为8位,无奇偶校验位,停止位为1位 RCSTA = 0b; // 启用串口模块,使能发送和接收TRISC6 = 1; // 将TX引脚设置为推挽输出模式TRISC7 = 0; // 将RX引脚设置为输入模式// 配置中断INTCON = 0b; // 启用全局中断,并设置触发方式为下降沿触发 PIR1 = 0b; // 清除串口接收中断标志位PIE1 = 0b; // 使能串口接收中断// 主循环while (1){// 在此处添加其他代码...}// 串口接收中断服务程序void __ISR _U1RXInterrupt(void) interrupt 5 using 2{char receivedByte;receivedByte = RCREG; // 读取接收到的字节// 在此处添加处理接收到的字节的代码...}```请注意,上述代码只是一个简单的示例,实际应用中可能需要根据具体需求进行修改和扩展。
PIC笔记
![PIC笔记](https://img.taocdn.com/s3/m/b74e9b8f84868762caaed53a.png)
OPTION/INTCON :用于控制TMR0/中断 bit7(NOT_RBPU):RB.0~.7上拉使能;RB口如有电平变化则置位,编程时应加以注意,可先统一置0或1.
PORTB :RB.0~.7均有弱上拉,RB.4~.7可设电平变化中断
TMR0/WDT :可无需CPU参与,由于其内部有独立的RC振荡器,不必系统时钟参与工作
选取某位:&,andlw,andwf
对某位取反:^,xorlw,xorwf
LSB(least significant bit):最低有效位
宏指令banksel<标号>:banksel为“体选”,<标号>为此前已定义过的一个寄存器
例:banksel portc,义为选择portc所在体即体0
2)OC门电路“必须加上拉电阻,才能使用”。
3)为加大输出引脚的驱动能力,有的单片机管脚也需使用上拉电阻。
4)在CMOS芯片上,为防止静电破坏,不用的引脚不能悬空。一般接上拉电阻降低输入阻抗,提供泄荷通道。
5)芯片的管脚加上拉电阻提高输出电平,从而提高芯片输入信号的噪声容限,增强抗干扰能力。
终端:通常指具有键盘和显示器而自身不具有数据出炉功能的装置,其数据处理功能放到远端的高速计算机实现
*用户自定义和程序用到的寄存器变量,应该尽量定义在70H~7FH。原因是对于16F877而言,无论当前的RAM体是哪个,都能访问到该区间的寄存器单元
*d'2'表示十进制2;a'2'表示字符2
*串行通信是一位一位的输入或输出,因此在校对每位正确与否时也是一位一位比对
2)从确保足够的驱动电流考虑应当足够小,电阻小,电流大。
PIC单片机中断程序的设计技巧
![PIC单片机中断程序的设计技巧](https://img.taocdn.com/s3/m/2e2db74c77c66137ee06eff9aef8941ea66e4b70.png)
PIC单片机中断程序的设计技巧设计PIC单片机中断程序时,需要根据具体的需求和硬件环境进行合理的设计。
下面是一些设计中断程序的技巧:1.确定中断触发源:首先需要确定中断是由什么触发的,例如定时器溢出、外部中断引脚等。
根据不同的触发源,可以选择不同的中断方式,如正边沿触发、负边沿触发等。
2.中断优先级设置:如果系统中存在多个中断源,需要明确中断的优先级。
可以通过优先级控制寄存器来设置不同中断的优先级,确保在同时触发多个中断的情况下,能够正确处理高优先级的中断。
3.中断服务程序的编写:中断服务程序是在中断发生时自动执行的程序,因此需要编写相应的中断服务程序。
中断服务程序的编写需要注意以下几点:-保持中断向量表的正确性:中断向量表保存了中断向量地址,确保中断服务程序被正确调用。
需要在程序中配置中断向量表的地址,并确保中断向量表的内容正确无误。
-快速响应中断并尽快执行中断服务程序:由于中断发生时需要尽快进行响应,所以中断服务程序需要尽可能地简短和高效。
可以通过减少循环次数、使用高效的算法等方式来提高中断服务程序的执行效率。
-使用全局变量:中断服务程序通常会修改全局变量的值,所以需要在设计中考虑全局变量的使用规则,防止数据冲突问题的发生。
可以通过使用互斥机制或者禁止一些中断来解决这个问题。
4.确定中断处理的顺序和时间:如果系统中存在多个中断源,需要明确中断处理的顺序和时间。
不同的中断源可能具有不同的优先级,所以需要在设计中明确不同中断的处理顺序,确保每个中断按照优先级进行处理。
5.合理的中断延迟时间:中断处理需要一定的时间,因此需要根据具体需求和硬件环境来确定合理的中断延迟时间。
如果中断处理时间过长,可能会导致系统响应速度变慢,影响整体性能。
因此需要合理地设置中断延迟时间,确保系统能够及时地响应中断。
6.中断嵌套的处理:在一些情况下,可能会存在中断嵌套的情况,即一些中断服务程序中又发生了另一个中断。
在设计中断程序时,需要考虑到中断嵌套的处理方式,例如设置屏蔽中断或者暂时禁止其他中断的发生,确保中断的处理顺序正确无误。
PIC单片机C语言编程实例
![PIC单片机C语言编程实例](https://img.taocdn.com/s3/m/0bb9e4e2e009581b6ad9eb02.png)
/*等待中断*/
1.1.2 程序清单
下面给出一个调试通过的例程,可作为读者的参考。调试该程序把模板 J7 上的短路跳 针拔下,以免产生冲突。
#include <pic1687x.h>
volatile unsigned char data;
TRISC=0x00;
/*SDO 引脚为输出,SCK 引脚为输出*/
}
1.2.3 程序清单
下面给出已经在实验板上调试通过的一个程序,可作为用户编制其它程序的参考。
#include
<pic1687x.h>
/*该程序用于在 8 个 LED 上依次显示 1~8 等 8 个字符*/
static volatile int table[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,
I;
unsigned char j;
const char table[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,0x8e,0x7f,0xbf,0x89,0xff};
/*B 口“电平变化中断”初始化子程序*/
/*启动发送*/
do
{
;
}while(SSPIF==0);
/*等待发送完毕*/
SSPIF=0;
/*清除 SSPIF 标志*/
}
/*主程序*/
main()
{
unsigned I;
initial();
PIC学习几个小知识点
![PIC学习几个小知识点](https://img.taocdn.com/s3/m/13ad2e65011ca300a6c390a9.png)
1、芯片PIC16F877A:今天遇到了一个问题,不知道C语言不支持还是编译器不支持,具体是这样的,我在主函数中申明了一个数组,然后调用一个函数,将这个数组以形参的方式传入那个函数,传的是这个数组的地址,也就是形参是指针,在被调用的函数中,我这样处理这个指针行不行?
void main()
{
unsigned int Year,month_day,Week_Hour,Min_Sec;
RCFGCALbits.RTCPTR = 3;//指针指到年
Year = RTCVAL;//年
month_day = RTCVAL;//月日
Week_Hour = RTCVAL;//周时
*RAM_Addr++ = month_day & 0x00FF;
*RAM_Addr++ = (month_day & 0xFF00) >> 8;
*RAM_Addr++ = Year & 0x00FF;
}
不能省略Year,因为它每次都是自减的!
PIC学习小知识点
1、今天晚上搞了一个晚上,就PIC单片机,按键不知道为什么总是进S3,说明S3一直被按下,查了好半天才发现,S3接在了RB3上,RB3在用来仿真的时候是不能用的,它是一直被拉低的,所以一直S3是按下的!
2011.10.17学习:
在PIC的一些中、低端型号中,往往只有一个中断函数入口,而且没有中断优先级,这对于很多在学校学习89C51核出来的学生,往往给他们带来一定的学习障碍。
SinusoidalBLDC.c: In function '_T1Interrupt':
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2 引ISB寄存器,使RB7~RB4相关的引脚处于输入状态;
◇如果需要弱上拉,通过OPTION_REG的第7位设置;
◇RBIF=O;
◇RBIE=1;
◇GIF=1。
响应状态变化后的中断服务程序。
bit SYSTime;
#defineTimeEnable()SYSTime=0,if(SYSlms){SYSTime=l;SYSlms=0;)
可以把TimeEnable()放到主程序死循环的任何地方,每当程序执行这个宏,SYSTime就会清零,这就是标志位的自我消失.如果在定时器时间基准标志位SYSlms已经置位的话,SYSTime就会置1,这样别的程序就可以利用这个时间消息了,这就是消息的自我发布。下面就是利用这个时间消息来进行按键延时去抖的,首先看一下按键扫描子程序;
首先,在定时器中断里设置一个lms的时间基准标志位“SYSlms”,每到lms,“SYSlms”便置位。程序如下:
unsigned char count;
if((ToIE&TOIF)==1){ //定时器中断
TMRO+=0x09; //每250μs中断一次
if(count==4){
if(RB4==0){ //RB4上的按钮接地
key=1; //按键标志位置位
}
RBIF=0; //清除引脚中断标志位
}
其中,if(RB4==0)语句相当于读取了PORTB端口数据寄存器,取消了状态变化的硬件信号。
下面详细介绍怎么样进行按键去抖。
void seaakey()
{
unsigned char KeyTime,KeyTask;//定义任务时间参数、
//任务参数
switch(KeyTask)
{
case0:if(key)
{
KeyTime=30; //准备延时30 ms
{
//调按键处理程序
KeyTask=0;
}
else KeyTask=0;//退出任务
break;
}
}
在主程序的死循环中这样用:
while(1){
TimeEnable();
If(SYSTime==1){scankey();)
◇检查RBIF是否为l,为l则是引脚变化引起的中断;
◇调用延时程序,延时20~30 ms,目的是为了按键去抖;
◇判断是引脚出现上升沿还是下降沿引起的中断;
◇调用按键处理程序;
◇读PORTB口的值,取消状态变化的硬件信号;
◇清除RBIF标志。
KeyTask++; //准备好下一个任务
key=0;
}
break;
case 1:KeyTime--; //延时30 ms
if(KeyTime==0) KeyTask++;
break;
case 2:if(RB4==o)
count=0;
SYSlms=l; //系统时间标志
couot++;
}
T0IF=0; //清除时钟中断标志位
}
有了这个时间基准,便可以在主程序里进行按键去抖处理了。为了更好地利用这个时间基准,定义一个消息标志SYSTime,笔者把它称作时间消息。为了让这个消息有自我发布和自我消失的功能.定义了如下一个宏:
//在此可以添加其他程序
只有有时问消息的时候才执行按键扫描程序。可以看到,进入扫描程序执行第一次的时候,程序首先判断按键标志位有没有置位,置位的话(也就是有按键按下的话),任务时间参数(KeyTime)赋值为30,这是延时30ms,去抖,当然你也可以设置为其他的时间值;同时任务参数 (KeyTask)加1。1ms后,再进入扫描程序,这个时候扫描程序执行casel的语句,这样30次后(延时了30ms),任务参数 (KeyTask)加1,值为2。lms后,再进入扫描程序,将执行case 2的语句,首先在这里再次判断是不是按键还在按下,如果是就调按键的处理程序,如果不是。就退出按键扫描程序。在这里,还可以加入按键是否抬起的判断程序。
下面给出笔者设计程序时的思路。
当引脚状态变化引起中断时,在中断子程序里首先判断引起中断的原因是不是我们需要的变化引起的中断。如果是,不要在这里延时,而是设置一个标志位,接着清除中断标志,退出中断。中断程序如下:
else if((RBIE&RBlF)==1){ //如果引脚变化引起中断
PIC单片机RB口中断程序设计
所有的中档系列PIC单片机,PORTB端口最高的4个引脚(RB7~RB4)在设为输入模式时,当输入电平由高到低或由低到高发生变化时,可以让单片机产生中断。这就是通常所说的引脚状态变化中断。
在设计引脚中断程序时,有三个需要特别注意的地方。一是,在清除P0RTB中断标志位RBIF之前,必须安排一条必不可少的,以PORTB端口数据寄存器 PORTB为源寄存器的读操作指令。放置这一指令的目的有时并不只是为了读取有用的数据,而是为了取消状态变化的硬件信号,以便顺利清除RBIF标志位,为下一次中断做好准备。二是,由于端口PORTB是引脚电子变化中断,即无论引脚出现上升沿还是下降沿都会产生中断请求,所以必须处理好不需要的虚假中断。三是,一般都利用PIC单片机的引脚功能来检测按键,所以必须处理好按键消抖的问題。
这样设计的引脚变化程序,CPU开销小,效率高,不会出现堆浅溢出的问题,提高了系统的实时性。
笔者认为上面程序设计最大的问题是在中断程序里调用延时程序。大家知道,中档PIC单片机只有8层深度的硬件堆栈,在中断里调用于程序出现极易堆栈溢出的情况。另外,PIC单片机中断程序人口只有一个,在响应中断的请求时,PIC单片机就会自动把全局中断的使能位(INTCON的第7位GIF)清除,这样其他中断就暂时不能被响应(此时,如果别的中断发出的中断请求,标志位将一直保留着),直到这个中断程序退出后才会得到响应。这就要求我们设计中断程序的时候必须尽量短,避免调用子程序,更不要在中断里进行复杂的运算。