PWM周期:20ms,也就是50Hz频率
由于用于控制舵机,高电平是0.5ms~2.5ms,所以打算把20ms分为200份,没份时间就是20ms/200=0.1ms,这样5份高电平就代表0.5ms了
单片机是常用的STC89C52RC,烧录程序后从示波器看波形却傻眼了....波形上面频率是170Hz左右,看了一晚上的程序居然没看出问题。所谓旁观者清,各位来指点指点吧。
程序如下,一看就懂
- /*********************************************************************************
- ====舵机驱动程序=========
- 编写:小刘
- 晶振:12MHz
- 舵机型号:MG996
- 舵机周期驱动信号周期:20ms
- 电压:4.8-7.2V
- **********************************************************************************/
- #include<reg52.h> //包含特殊功能寄存器的定义
- sbit p11=P1^1;//输出pwm脉冲
- #define uchar unsigned char
- #define uint unsigned int
- /* 函数&变量申明 -----------------------------------------------*/
- void Init_Timer0(void); //定时器定时20ms,分为200份,每份时间0.1ms=100us
- void Init_Uart() ;
- uchar receive;
- uchar pwm=25;//阀值,25就是2.5ms 的高电平时间
- uchar period=200;//舵机信号周期20ms,分成200份
- uchar i=0;//用于计数
- bit temp=0;
- /*
- ********************************************************************************
- ** 函数名称 : main(void)
- ** 函数功能 : 主函数
- ********************************************************************************
- */
- main()
- {
- Init_Timer0();
- Init_Uart() ;
- while(1);
- }
- /*
- ********************************************************************************
- ** 函数名称 : Init_Timer0(void)
- ** 函数功能 : 定时器初始化子程序
- ********************************************************************************
- */
- void Init_Timer0(void) //定时器初始化子程序
- {
- TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
- //给定初值,每份定时时间0.1ms,一个周期200份=20ms
- TH0=(65535-100)/256;//0XFF
- TL0=(65535-100)%256;//0X9C
- EA=1; //总中断打开
- ET0=1; //定时器中断打开
- TR0=1; //定时器开关打开
- }
- /*
- ********************************************************************************
- ** 函数名称 : void Init_Uart()
- ** 函数功能 : 串口初始化子程序
- ********************************************************************************
- */
- void Init_Uart()
- {
- TMOD=0x20; //用定时器设置串口波特率
- TH1=0xfd;
- TL1=0xfd;
- TR1=1;
- REN=1; //串口初始化
- SM0=0;
- SM1=1;
- EA=1; //开启总中断
- ES=1; //开串口中断
- }
- /*
- ********************************************************************************
- ** 函数名称 : Timer0_isr(void) interrupt 1 using 1
- ** 函数功能 : 定时器中断程序
- ********************************************************************************
- */
- void Timer0_isr(void) interrupt 1
- {
- TH0=(65535-100)/256;
- TL0=(65535-100)%256;
- i++;
- if (i>=pwm)p11=0; //如果超过了阀值就是电平
- if (i==200){i=0;p11=1;} //0.1ms*200=20ms 周期时间到,默认给输出高电平
- }
- /*
- ********************************************************************************
- ** 函数名称 : void Uart()
- ** 函数功能 : 串口接收中断程序
- ********************************************************************************
- */
- void Uart() interrupt 4 //串口中断响应程序
- {
- ES=0;//关闭串口中断
- if(RI)
- {
- RI=0;//清除接收中断标志位
- receive=SBUF;//读取SBUF
- }
- ES=1;//打开串口中断
- }
复制代码
对啊,周期就是17.5+2.5=20ms,频率就是50Hz了啊,光是这样的都没法达到预期...
嗯嗯,这个得明天再去实验室看看了。光从程序上您能看出明显的问题吗?
问题已找到,我的TMOD在初始化串口定时器1的时候用了“=”而不是“|=“,结果可想而知。但是新的问题出现,我现在的频率是40Hz左右...用 TH0=(65535-100)/256;TL0=(65535-100)%256; 误差如此之大?
- TH0=(65535-78)/256;
- TL0=(65535-78)%256;
复制代码并且循环200次,居然是20ms,和理论差太多了,求大神降临啊
一周热门 更多>