完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
用T0解码红外键码一切正常,用T2单独软件模拟PWM输出也是正常(用两个按键控制占空大小也是正常的),但是将两段代码结合后PWM输出就没有变化了,红外解码一切正常,请教高手
完整代码如下: #include //#define byte unsigned char //#define word unsigned int #define MAIN_Fosc 24000000UL //定义主时钟 #define PWM_DUTY 6000 //定义PWM的周期,数值为时钟周期数,假如使用24.576MHZ的主频,则PWM频率为6000HZ。 #define PWM_HIGH_MIN 32 //限制PWM输出的最小占空比。用户请勿修改。 #define PWM_HIGH_MAX (PWM_DUTY-PWM_HIGH_MIN) //限制PWM输出的最大占空比。用户请勿修改。 typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32; sfr TL2 = 0xD7; sfr TH2 = 0xD6; sfr IE2 = 0xAF; //STC12C5A60S2系列 sfr P3M1 = 0xB1; //P3M1.n,P3M0.n =00--->Standard, 01--->push-pull sfr P3M0 = 0xB2; // =10--->pure input, 11--->open drain sfr AUXR = 0x8E; sfr INT_CLKO = 0x8F; ***it P_PWM = P3^0; //定义PWM输出引脚。 ***it IR=P3^2; //将IR 位定义为 P3.2引脚 //***it P30=P3^0; ***it P33=P3^3; ***it P31=P3^1; ***it P34=P3^4; ***it P35=P3^5; bit k1,k2; u8 a[4]; //储存用户码、用户反码与键数据码、键数据反码 u16 Lowtime,HighTime; //储存高、低电平的宽度 u16 pwm; //定义PWM输出高电平的时间的变量。用户操作PWM的变量。 u16 PWM_high,PWM_low; //中间变量,用户请勿修改。 void delay_ms(u8 ms); void LoadPWM(u16 i); /************************************************************ 函数功能:reset *************************************************************/ void reset(void) { P33=1; P31=1; P34=1; P35=1; } /************************************************************ 函数功能:delay *************************************************************/ void delay(u8 n) { u16 x; while (n--) { x = 0; while (++x); } } /************************************************************ 函数功能:对 4个字节的用户码和键数据码进行解码 说明:解码正确,返回 1,否则返回 0 出口参数:dat *************************************************************/ bit DeCode(void) { u8 i,j; u8 temp; //储存解码出的数据 for(i=0;i<4;i++) //连续读取4 个用户码和键数据码 { for(j=0;j<8;j++) //每个码有 8 位数字 { temp=temp>>1; //temp 中的各数据位右移一位,因为先读出的是高位数据 TH0=0; //定时器清 0 TL0=0; //定时器清 0 TR0=1; //开启定时器 T0 while(IR==0) //如果是低电平就等待 ; //低电平计时 TR0=0; //关闭定时器 T0 LowTime=TH0*256+TL0; //保存低电平宽度 TH0=0; //定时器清 0 TL0=0; //定时器清 0 TR0=1; //开启定时器 T0 while(IR==1) //如果是高电平就等待 ; TR0=0; //关闭定时器 T0 HighTime=TH0*256+TL0; //保存高电平宽度 if((LowTime<370)||(LowTime>640)) return 0; //如果低电平长度不在合理范围,则认为出错,停止解码 if((HighTime>420)&&(HighTime<620)) //如果高电平时间在560微秒左右,即计数560/1次 temp=temp&0x7f; //(520-100=420, 520+100=620),则该位是 0 if((HighTime>1300)&&(HighTime<1800)) //如果高电平时间在 1680微秒左右,即计数 1680 1.085=1548 次 temp=temp|0x80; //(1550-250=1300,1550+250=1800),则该位是 1 } a=temp; //将解码出的字节值储存在 a } if(a[2]=~a[3]) //验证键数据码和其反码是否相等,一般情况下不必验证用户码 return 1; //解码正确,返回 1 } /************************************************************ 函数功能:执行遥控功能 *************************************************************/ void Function(void) { //EA=0; if(a[2]==0xEE) { //k1=0; //delay(15); //while(pwm < (PWM_HIGH_MAX-8)&&k1==0) //{ pwm += 16; //PWM逐渐加到最大 LoadPWM(pwm); delay_ms(2); //} // k1=1; } if(a[2]==0x99) { //k2=0; //delay(15); // while(pwm > (PWM_HIGH_MAX-8)&&k2==0) //{ pwm -= 16; //PWM逐渐减到最小 LoadPWM(pwm); delay_ms(2); // } // k2=1; } if(a[2]==0xAA) { delay(2); P33=0; P31=1; P34=0; P35=1; delay(15); reset(); } if(a[2]==0xCC) { delay(2); P33=1; P31=0; P34=0; P35=1; delay(3); reset(); } if(a[2]==0x22) { delay(2); P33=0; P31=1; P34=1; P35=0; delay(3); reset(); } if(a[2]==0x66) { delay(2); P33=1; P31=0; P34=1; P35=0; delay(15); reset(); } //EA=1; } /************************************************************ 函数功能:主函数 *************************************************************/ void main() { EA=1; //开启总中断 EX0=1; //开外中断 0 ET0=1; //定时器 T0中断允许 IT0=1; //外中断的下降沿触发 TMOD=0x01; //使用定时器 T0的模式 1 TR0=0; //定时器T0 关闭 P_PWM = 1; P3M1 &= ~1; //P3.0 设置为推挽输出 P3M0 |= 1; AUXR &= ~(1<<4); //停止计数 IE2 |= (1<<2); //允许中断 AUXR |= (1<<2); //1T AUXR &= ~(1<<3); //定时 INT_CLKO |= 0x04; //输出时钟 TH2 = 0; TL2 = 0; AUXR |= (1<<4); //开始运行 pwm = PWM_DUTY / 10; //给PWM一个初值,这里为10%占空比 //pwm = 32; LoadPWM(pwm); //计算PWM重装值 while(1) //等待红外信号产生的中断 ; } //======================================================================== // 函数: void delay_ms(u8 ms) // 描述: 延时函数。 // 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟. // 返回: none. // 版本: VER1.0 // 日期: 2013-4-1 // 备注: //======================================================================== void delay_ms(u8 ms) { unsigned int i; do{ i = MAIN_Fosc / 13000; while(--i) ; }while(--ms); } /**************** 计算PWM重装值函数 *******************/ void LoadPWM(u16 i) { u16 j; if(i > PWM_HIGH_MAX) i = PWM_HIGH_MAX; //如果写入大于最大占空比数据,则强制为最大占空比。 if(i < PWM_HIGH_MIN) i = PWM_HIGH_MIN; //如果写入小于最小占空比数据,则强制为最小占空比。 j = 65536UL - PWM_DUTY + i; //计算PWM低电平时间 i = 65536UL - i; //计算PWM高电平时间 EA = 0; PWM_high = i; //装载PWM高电平时间 PWM_low = j; //装载PWM低电平时间 EA = 1; } /************************************************************ 函数功能:红外线触发的外中断处理函数 *************************************************************/ void Int0(void) interrupt 0 using 0 { EX0=0; //关闭外中断 0,不再接收二次红外信号的中断,只解码当前红外信号 TH0=0; //定时器T0 的高 8位清 0 TL0=0; //定时器T0 的低 8位清 0 TR0=1; //开启定时器 T0 while(IR==0) //如果是低电平就等待,给引导码低电平计时 ; TR0=0; //关闭定时器T0 LowTime=TH0*256+TL0; //保存低电平时间 TH0=0; //定时器T0 的高 8位清 0 TL0=0; //定时器T0 的低 8位清 0 TR0=1; //开启定时器 T0 while(IR==1) //如果是高电平就等待,给引导码高电平计时 ; TR0=0; //关闭定时器 T0 HighTime=TH0*256+TL0; //保存引导码的高电平长度 if((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700)) { //如果是引导码,就开始解码,否则放弃,引导码的低电平计时 //次数=9000us/1.085=8294, 判断区间:8300-500=7800,8300+500=8800. if(DeCode()==1) Function(); //如果满足条件,执行遥控功能 //EA=0; } EX0=1; //开启外中断 EX0 } /********************* Timer2中断函数************************/ void timer2_int (void) interrupt 12 { if(P_PWM) { //P34=P_PWM ; TH2 = (u8)(PWM_low >> 8); //如果是输出高电平,则装载低电平时间。 TL2 = (u8)PWM_low; } else { //P34=P_PWM; TH2 = (u8)(PWM_high >> 8); //如果是输出低电平,则装载高电平时间。 TL2 = (u8)PWM_high; } } |
|
相关推荐
16个回答
|
|
|
|
|
|
两段代码结合后,原本想用0xEE和0x99控制占空比的大小,但是输出一直没有变化
这个程序本来想用来控制遥控小车的,之前没用PWM直接控制输出的话也可以完成小车的前进后退左转右转,但是启动停止惯性太大,所以想引入PWM加减速,结果研究了几天都无果 |
|
|
|
|
|
|
|
好的,谢谢,但是我的红外部分一直在正常使用,看有没有改进空间
|
|
|
|
这是说到点子上了,谢谢了
|
|
|
|
基本发现问题了,就是红外解码后就在void Function(void) 这个函数里面挑不出来了,奇怪的是连T2的中断也不执行了,现在想请教大家执行完功能函数后如何跳回主函数,继续执行T2的PWM输出
|
|
|
|
你把Function(); 放到大循环里面调用.不就没事了.不管怎么着.T2中断会运行呀.
|
|
|
|
这个想法很好,我下班回去试试,多谢!
|
|
|
|
#include
#include "intrins.h" typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32; sfr TL2 = 0xD7; sfr TH2 = 0xD6; sfr IE2 = 0xAF; //STC12C5A60S2系列 sfr P3M1 = 0xB1; //P3M1.n,P3M0.n =00--->Standard, 01--->push-pull sfr P3M0 = 0xB2; // =10--->pure input, 11--->open drain sfr AUXR = 0x8E; ***it IR=P3^2; //将IR 位定义为 P3.2引脚 ***it P30=P3^0; ***it P33=P3^3; ***it P31=P3^1; ***it P34=P3^4; ***it P35=P3^5; bit flag; u8 k1,k2; u8 a[4]; //储存用户码、用户反码与键数据码、键数据反码 u16 LowTime,HighTime; //储存高、低电平的宽度 /************************************************************ 函数功能:对 4个字节的用户码和键数据码进行解码 说明:解码正确,返回 1,否则返回 0 出口参数:dat *************************************************************/ bit DeCode(void) { u8 i,j; u8 temp; //储存解码出的数据 for(i=0;i<4;i++) //连续读取4 个用户码和键数据码 { for(j=0;j<8;j++) //每个码有 8 位数字 { temp=temp>>1; //temp 中的各数据位右移一位,因为先读出的是高位数据 TH0=0; //定时器清 0 TL0=0; //定时器清 0 TR0=1; //开启定时器 T0 while(IR==0) //如果是低电平就等待 ; //低电平计时 TR0=0; //关闭定时器 T0 LowTime=TH0*256+TL0; //保存低电平宽度 TH0=0; //定时器清 0 TL0=0; //定时器清 0 TR0=1; //开启定时器 T0 while(IR==1) //如果是高电平就等待 ; TR0=0; //关闭定时器 T0 HighTime=TH0*256+TL0; //保存高电平宽度 if((LowTime<370)||(LowTime>640)) return 0; //如果低电平长度不在合理范围,则认为出错,停止解码 if((HighTime>420)&&(HighTime<620)) //如果高电平时间在560微秒左右,即计数560/1次 temp=temp&0x7f; //(520-100=420, 520+100=620),则该位是 0 if((HighTime>1300)&&(HighTime<1800)) //如果高电平时间在 1680微秒左右,即计数 1680 1.085=1548 次 temp=temp|0x80; //(1550-250=1300,1550+250=1800),则该位是 1 } a=temp; //将解码出的字节值储存在 a } if(a[2]=~a[3]) //验证键数据码和其反码是否相等,一般情况下不必验证用户码 return 1; //解码正确,返回 1 } ******************************************** 函数功能:主函数 *************************************************************/ void main() { EX0=1; //开外中断 0 ET0=1; //定时器 T0中断允许 IT0=1; //外中断的下降沿触发 TMOD=0x01; //使用定时器 T0的模式 1 TR0=0; //定时器T0 关闭 AUXR &= ~(1<<4); //停止计数 IE2 |= (1<<2); //允许中断 AUXR |= (1<<2); //1T AUXR &= ~(1<<3); //定时 TH2 = (65536-46083)/256; TL2 = (65536-46083)%256; AUXR |= (1<<4); //开始运行 k1=0; k2=0; EA=1; //开启总中断 while(1) //等待红外信号产生的中断 { if((flag==1)&&(a[2]==0x99)) { EA=0; AUXR &= ~(1<<4); //停止计数 P30=!P30; k1=0; k2=0; TH2 = (65536-46083)/256; TL2 = (65536-46083)%256; AUXR |= (1<<4); //开始计数 EA=1; flag=0; } } ; } /************************************************************ 函数功能:红外线触发的外中断处理函数 *************************************************************/ void Int0(void) interrupt 0 using 0 { EX0=0; //关闭外中断 0,不再接收二次红外信号的中断,只解码当前红外信号 TH0=0; //定时器T0 的高 8位清 0 TL0=0; //定时器T0 的低 8位清 0 TR0=1; //开启定时器 T0 while(IR==0) //如果是低电平就等待,给引导码低电平计时 ; TR0=0; //关闭定时器T0 LowTime=TH0*256+TL0; //保存低电平时间 TH0=0; //定时器T0 的高 8位清 0 TL0=0; //定时器T0 的低 8位清 0 TR0=1; //开启定时器 T0 while(IR==1) //如果是高电平就等待,给引导码高电平计时 ; TR0=0; //关闭定时器 T0 HighTime=TH0*256+TL0; //保存引导码的高电平长度 if((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700)) { //如果是引导码,就开始解码,否则放弃,引导码的低电平计时 //次数=9000us/1.085=8294, 判断区间:8300-500=7800,8300+500=8800. if(DeCode()==1) flag=1; //Function(); //如果满足条件,执行遥控功能 //EA=0; } EX0=1; //开启外中断 EX0 } /********************* Timer2中断函数************************/ void timer2_int (void) interrupt 12 { k1++; k2++; if(k1==2) { P31=1; k1=0; } if(k2==8) { P31=0; k2=0; } } |
|
|
|
去掉了所有的延时,只对P30进行翻转,PWM还是异常,看来要放弃这种思路了,准备采用2片stc15f104W,一片专门负责红外解码,并输出加减信号到P34和P35,然后通过光耦触发第二片专门负责PWM的相应端口完成PWM占空比的调节,目前来看这能这样了。实在不想耗时间了。。。
|
|
|
|
没有必要吧.时间再长一点.这个问题解决了.你将来遇到类似问题都解决了.你换两个芯片 来解决这个问题不是正解呀.
你的解码程序还是放在中断里面进行的呀.还是在中断里面死等高电平或者低电平呀.这个方法,当然没有办法完成这个项目了. 不是说移植我的解码程序吗?不见效果.?? |
|
|
|
我整理了一下,看能不能帮上你.
void init(void) { EX0 = 1; //使能INT0外部中断 ,引脚INT0接红外接收头DATA IT0 = 1; //下降沿触发 TMOD=0x11 ; //ET0=1;//打开定时器0中断,可以不打开 TR0=1;//打开定时器0,跑起来定时器0 EA=1; } void process_int(void) { static uc yw ; int_if=0; if( tc< 6 ){yw>>=1;wei++;} //脉宽0 else if( tc<=12 ){yw>>=1;yw|=0x80;wei++;} //脉宽1 else wei=0; if( (wei&7)==0 )buf[(wei>>3) ]=yw; //有8个BIT,记录到BUF内 if(wei==32)EX0=0;//收到32个位,也就是四个字节.数据够了.停止接收,关外部中断 } void process_ir(void) {static uc i; ui id ; id = (buf[1]<<8) + buf[2]; if( (buf[3]|buf[4])==0xff) //收到遥控信息,并且验证码正确 { //解码成功 } for(i=0;i<6;i++)buf=0xff; wei=0; EX0=1; } void main(void) { //硬件 12 M 晶振 init(); while(1) { if(int_if)process_int(); if(EX0==0)process_ir(); } } void INT0_DOWN()interrupt 0 using 0 { TR0=0; // 停止定时器计数 tc = TH0;//读取定时器计数值 TH0= TL0=0; //清除定时器0计数值 //清定时器0 int_if=1;// 触发一个标志位, TR0=1; //再次打开定时器0 } |
|
|
|
非常感谢啊,本来要移植你的程序的,但大概看了一下,你已经用了2个定时器,我的PWM就没有定时器可用了,所以就没移植了,非常感谢你的帮助。
|
|
|
|
仔细拜读了你整理的程序,我觉得应该可以单芯片实现我要的功能了,由于现在主业是平面设计,你的程序只能下班回家实验了,我看你的主业就是单片机相关,真不错啊,我之前在深圳做过6年的机械设计4年的工业多轴机器人总成,那时候都用PLC和DSP(方案都是现成的)来实现的,总想往单片机方面发展一下,但迫于生活,只能暂时把单片机做为兴趣爱好了。有机会要拜你为师哈。
|
|
|
|
客气了。
|
|
|
|
用你整理的解码程序,基本完成了T0和T2互不干扰了,目前来看,低频的PWM基本可以做到用红外来调节占空比,高频的还是有些问题,接下来继续分析解决,再次感谢啊,呵呵。
|
|
|
|
只有小组成员才能发言,加入小组>>
3319 浏览 9 评论
2997 浏览 16 评论
3495 浏览 1 评论
9065 浏览 16 评论
4088 浏览 18 评论
1185浏览 3评论
611浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
601浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2337浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1898浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 23:16 , Processed in 1.520271 second(s), Total 80, Slave 70 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号
|