完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PIC单片机的中断跟51单片机的中断书写有点不一样,PIC的所有中断都在一个函数里,然后根据寄存器的标志位来识别是哪个硬件引发中断,比如: //中断 void interrupt timer1rbint(void) { if(ADIF==1&&ADIE==1) //AD转换完成中断 { TMR1IE=0; //禁止定时中断,避免两个中断相互扯淡 ADIF=0; //清除中断标志 AD_Flag=1; //置AD转换完成标志 TMR1IE=1; //允许定时中断 } 我看PICC和PIC18的编译器都是这样书写的习惯,好像到了PIC24系列用的C30编译器就有点不一样,每个中断都有它独立的子函数。 |
|
|
|
|
|
|
|
|
鸿哥,我来给你打下手,哈哈,顺便修炼下自己的内功,哈哈。 |
|
|
|
|
|
|
|
|
我跟你的缘分来日方长,不在乎现在的朝朝暮暮。 你现在最重要的是学习,打好基础,机遇总是青睐有准备的人。 |
|
|
|
|
|
|
|
|
是,最近这几天在搞uCGUI的移植,搞好了出个教程,呵呵。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
第三个程序51移植
/*鸿哥第三个程序移植*/ /*******手上的元件有限,所以修改了一些地方,原理相同。。。。。******************************/ /*加了三位数码管显示AD的值,以便调节按键按下时电压对应的AD数值,我用的是一个电位器来代替的按钮,加上数码管以后便于调试。 /*第三节:AD按键扫描与蜂鸣器 (1)AD按键可以实现一个IO口驱动几个按键的目的,以鸿哥的经验,一个IO口控制的按键数量最好不要超过3个。从实际应用来考虑,独立按键的方式最好,其次是行列按键,最次是AD按键。 (2)功能需求:按下按键1 LED 亮;按下按键2 LED 灭;按下按键3 LED 亮 (3)硬件原理: (a)用4个电阻竖着串联起来,最上端接5V,最下端接地。从上往下,最上端接5V的算第一个节点,最下端接地算最后一个节点,共5个节点。用一个带AD的IO口连接到第2个节点上,此节点上连接第一个按键,按键的另一端接地。以此方式,第二个按键连接到第3个节点,第三个按键连接到第4个节点。这4个电阻的目的主要是用来分压,靠不同的电压来识别不同的按键。 (b)用1个IO接了一个LED灯低电平有效 (4)源码适合的单片机:STC12C5A60S2(自带AD),晶振为12MHz**************************************** (5)源代码讲解如下: */ #include #include /********************STC12C5A60S2单片机的寄存器置位定义************/ #define ADC_POWER 0x80 #define ADC_FLAG 0x10 #define ADC_START 0x08 #define ADC_SPEEDLL 0x00 #define ADC_SPEEDL 0x20 #define ADC_SPEEDH 0x40 #define ADC_SPEEDHH 0x60 #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换数码管显示 #define cnt_delay_cnt1 40 //按键去抖动延时阀值 //#define cnt_voice_time 75 //蜂鸣器响的声音长短的延时阀值 #define cnt_key_nc 185 //没有按键按下时电压对应的AD数值 #define cnt_key1_up 10 //1号按键按下时电压对应的AD数值上限 #define cnt_key2_down 117 //2号按键按下时电压对应的AD数值下限 #define cnt_key2_up 137 //2号按键按下时电压对应的AD数值上限 #define cnt_key3_down 160 //3号按键按下时电压对应的AD数值下限 #define cnt_key3_up 175 //3号按键按下时电压对应的AD数值上限 ***it LATCH1=P2^2;//定义锁存使能端口 段锁存 ***it LATCH2=P2^3;// 位锁存 ***it LED=P3^0; // LED unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9 unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码 unsigned char TempData[8]; //存储显示值的全局变量 unsigned char num=0; //读回的AD值给数码管 unsigned char key_value=0; //读回的AD值给按键扫描函数用于比较,判断是那个按键输入 unsigned int delay_cnt1=0; //延时计数器的变量 unsigned char key_lock1=0; //按键自锁标志 //unsigned int voice_time_cnt; //蜂鸣器响的声音长短的计数延时 unsigned char key_sec=0; //哪个按键被触发 /**************************函数声明********************************/ void Display(unsigned char FirstBit,unsigned char Num); //数码管扫描显示 void InitADC(); //AD中断函数 void Delay(unsigned char n); //延时函数 void key_scan(); //按键扫描函数,放在定时中断里 void key_service(); //按键服务函数,放在main函数循环里 main() { TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 TH0=0x1c; //给定初值,这里使用定时器1ms TL0=0x18; EA=1; //总中断 ET0=1; // 打开定时器T0中断 EADC=1; //AD中断 TR0=1; //开定时器 IPH=0x02; //中断优先级 IP=0x02; InitADC(); while (1) //主循环 { key_service(); //按键服务函数,放在main函数循环里 TempData[0]=dofly_DuanMa[num/100]; TempData[1]=dofly_DuanMa[(num%100)/10]; TempData[2]=dofly_DuanMa[(num%100)%10]; Delay(2); Display(0,3); } } /************数码管显示********************/ void Display(unsigned char FirstBit,unsigned char Num) { static unsigned char i=0; DataPort=0; //清空数据,防止有交替重影 LATCH1=1; //段锁存 LATCH1=0; DataPort=dofly_WeiMa[i+FirstBit]; //取位码 LATCH2=1; //位锁存 LATCH2=0; DataPort=TempData[i]; //取显示数据,段码 LATCH1=1; //段锁存 LATCH1=0; i++; if(i==Num) i=0; } /**************AD初始化函数***************************/ void InitADC() { P1ASF = 0x01; ADC_RES = 0; ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 0x00; Delay(2); } /**************************延时函数*******************/ void Delay(unsigned char n) { unsigned char x; while (n--) { x = 5000; while (x--); } } /*********************AD中断函数************************************/ void adc_isr() interrupt 5 using 1 { ADC_CONTR &= !ADC_FLAG; num=ADC_RES; key_value=ADC_RES; //跟电压成比例关系的AD数值 ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 0x00; } /***********************定时器中断函数******************/ void Timer0_isr(void) interrupt 1 using 2 { TH0=0x1c; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出 TL0=0x18; key_scan(); //按键扫描函数,放在定时中断里 } /********************按键扫描函数**************/ void key_scan() //按键扫描函数 { if(key_value>cnt_key_nc) //空闲,没有按下 { key_lock1=0; //按键自锁标志清零 delay_cnt1=0; //按键去抖动延时计数器清零,此行非常巧妙 } else if(key_lock1==0) //有按键按下,且是第一次被按下 { if(key_value ++delay_cnt1; //延时计数器 if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 LED=0; key_sec=1; //触发1号键 } } else if(key_value> cnt_key2_down&&key_value< cnt_key2_up) //K2按下 { ++delay_cnt1; //延时计数器 if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 LED=1; key_sec=2; //触发2号键 } } else if(key_value> cnt_key3_down&&key_value< cnt_key3_up) //K3按下 { { ++delay_cnt1; //延时计数器 if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 LED=0; key_sec=3; //触发3号键 } } } } void key_service() //按键服务函数 { switch(key_sec) //按键服务状态切换 { case 1:// 1号键 LED=0; key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发 // key_lock1=0; //按键自锁标志清零 我用的是电位器所以要在这儿清一下零 break; case 2:// 2号键 LED=1; key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发 // key_lock1=0; //按键自锁标志清零 我用的是电位器所以要在这儿清一下零 break; case 3://3号键 LED=0; key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发 // key_lock1=0; //按键自锁标志清零 我用的是电位器所以要在这儿清一下零 break; } } |
|
|
|
|
|
|
|
|
/*鸿哥第三个程序移植*/
/*******手上的元件有限,所以修改了一些地方,原理相同。。。。。******************************/ /*加了三位数码管显示AD的值,以便调节按键按下时电压对应的AD数值,我用的是一个电位器来代替的按钮,加上数码管以后便于调试。 /*第三节:AD按键扫描与蜂鸣器 (1)AD按键可以实现一个IO口驱动几个按键的目的,以鸿哥的经验,一个IO口控制的按键数量最好不要超过3个。从实际应用来考虑,独立按键的方式最好,其次是行列按键,最次是AD按键。 (2)功能需求:按下按键1 LED 亮;按下按键2 LED 灭;按下按键3 LED 亮 (3)硬件原理: (a)用4个电阻竖着串联起来,最上端接5V,最下端接地。从上往下,最上端接5V的算第一个节点,最下端接地算最后一个节点,共5个节点。用一个带AD的IO口连接到第2个节点上,此节点上连接第一个按键,按键的另一端接地。以此方式,第二个按键连接到第3个节点,第三个按键连接到第4个节点。这4个电阻的目的主要是用来分压,靠不同的电压来识别不同的按键。 (b)用1个IO接了一个LED灯低电平有效 (4)源码适合的单片机:STC12C5A60S2(自带AD),晶振为12MHz**************************************** (5)源代码讲解如下: */ #include #include /********************STC12C5A60S2单片机的寄存器置位定义************/ #define ADC_POWER 0x80 #define ADC_FLAG 0x10 #define ADC_START 0x08 #define ADC_SPEEDLL 0x00 #define ADC_SPEEDL 0x20 #define ADC_SPEEDH 0x40 #define ADC_SPEEDHH 0x60 #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换数码管显示 #define cnt_delay_cnt1 40 //按键去抖动延时阀值 //#define cnt_voice_time 75 //蜂鸣器响的声音长短的延时阀值 #define cnt_key_nc 185 //没有按键按下时电压对应的AD数值 #define cnt_key1_up 10 //1号按键按下时电压对应的AD数值上限 #define cnt_key2_down 117 //2号按键按下时电压对应的AD数值下限 #define cnt_key2_up 137 //2号按键按下时电压对应的AD数值上限 #define cnt_key3_down 160 //3号按键按下时电压对应的AD数值下限 #define cnt_key3_up 175 //3号按键按下时电压对应的AD数值上限 ***it LATCH1=P2^2;//定义锁存使能端口 段锁存 ***it LATCH2=P2^3;// 位锁存 ***it LED=P3^0; // LED unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9 unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码 unsigned char TempData[8]; //存储显示值的全局变量 unsigned char num=0; //读回的AD值给数码管 unsigned char key_value=0; //读回的AD值给按键扫描函数用于比较,判断是那个按键输入 unsigned int delay_cnt1=0; //延时计数器的变量 unsigned char key_lock1=0; //按键自锁标志 //unsigned int voice_time_cnt; //蜂鸣器响的声音长短的计数延时 unsigned char key_sec=0; //哪个按键被触发 /**************************函数声明********************************/ void Display(unsigned char FirstBit,unsigned char Num); //数码管扫描显示 void InitADC(); //AD中断函数 void Delay(unsigned char n); //延时函数 void key_scan(); //按键扫描函数,放在定时中断里 void key_service(); //按键服务函数,放在main函数循环里 main() { TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 TH0=0x1c; //给定初值,这里使用定时器1ms TL0=0x18; EA=1; //总中断 ET0=1; // 打开定时器T0中断 EADC=1; //AD中断 TR0=1; //开定时器 IPH=0x02; //中断优先级 IP=0x02; InitADC(); while (1) //主循环 { key_service(); //按键服务函数,放在main函数循环里 TempData[0]=dofly_DuanMa[num/100]; TempData[1]=dofly_DuanMa[(num%100)/10]; TempData[2]=dofly_DuanMa[(num%100)%10]; Delay(2); Display(0,3); } } /************数码管显示********************/ void Display(unsigned char FirstBit,unsigned char Num) { static unsigned char i=0; DataPort=0; //清空数据,防止有交替重影 LATCH1=1; //段锁存 LATCH1=0; DataPort=dofly_WeiMa[i+FirstBit]; //取位码 LATCH2=1; //位锁存 LATCH2=0; DataPort=TempData[i]; //取显示数据,段码 LATCH1=1; //段锁存 LATCH1=0; i++; if(i==Num) i=0; } /**************AD初始化函数***************************/ void InitADC() { P1ASF = 0x01; ADC_RES = 0; ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 0x00; Delay(2); } /**************************延时函数*******************/ void Delay(unsigned char n) { unsigned char x; while (n--) { x = 5000; while (x--); } } /*********************AD中断函数************************************/ void adc_isr() interrupt 5 using 1 { ADC_CONTR &= !ADC_FLAG; num=ADC_RES; key_value=ADC_RES; //跟电压成比例关系的AD数值 ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 0x00; } /***********************定时器中断函数******************/ void Timer0_isr(void) interrupt 1 using 2 { TH0=0x1c; //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出 TL0=0x18; key_scan(); //按键扫描函数,放在定时中断里 } /********************按键扫描函数**************/ void key_scan() //按键扫描函数 { if(key_value>cnt_key_nc) //空闲,没有按下 { key_lock1=0; //按键自锁标志清零 delay_cnt1=0; //按键去抖动延时计数器清零,此行非常巧妙 } else if(key_lock1==0) //有按键按下,且是第一次被按下 { if(key_value ++delay_cnt1; //延时计数器 if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 LED=0; key_sec=1; //触发1号键 } } else if(key_value> cnt_key2_down&&key_value< cnt_key2_up) //K2按下 { ++delay_cnt1; //延时计数器 if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 LED=1; key_sec=2; //触发2号键 } } else if(key_value> cnt_key3_down&&key_value< cnt_key3_up) //K3按下 { { ++delay_cnt1; //延时计数器 if(delay_cnt1>cnt_delay_cnt1) { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 LED=0; key_sec=3; //触发3号键 } } } } void key_service() //按键服务函数 { switch(key_sec) //按键服务状态切换 { case 1:// 1号键 LED=0; key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发 // key_lock1=0; //按键自锁标志清零 我用的是电位器所以要在这儿清一下零 break; case 2:// 2号键 LED=1; key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发 // key_lock1=0; //按键自锁标志清零 我用的是电位器所以要在这儿清一下零 break; case 3://3号键 LED=0; key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发 // key_lock1=0; //按键自锁标志清零 我用的是电位器所以要在这儿清一下零 break; } } |
|
|
|
|
|
|
|
|
呵呵,移植成功。又学了不少。。把您的全移植完,我也会不会成高手啊。。哈哈 |
|
|
|
|
|
|
|
|
恭喜。确实很有热情,把我的全部移植完,何止是高手,鸿哥也会被你拍在沙滩上。 |
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2382 浏览 1 评论
4242 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2619 浏览 2 评论
3118 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4577 浏览 5 评论
有套STM32与西门子200程序需要代写,有兴趣的工程师与有联系!
2491浏览 1评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6801浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-18 03:53 , Processed in 0.986597 second(s), Total 83, Slave 74 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖