本帖最后由 asiavikin 于 2014-10-7 22:20 编辑
各位大能:
我想编写一个89c52下控制舵机运行的c程序,实现从串口
逐次控制pwm方波占空比的功能。比如,从串口向
单片机发送一次ff010aff后,方波的宽度就增大一点;发送多次ff010aff后,方波的宽度就可以增大到最多2毫秒。如果发送ff010bff,方波宽度就应该减小,发送多次ff010bff后,方波的宽度就可以减小到最少0.5毫秒。
我在网上找到了一个程序,把它修改了一下后用
proteus仿真,但我发现并不能象我想的那样
逐次控制pwm方波:从串口输出了命令ff010aff后,方波的宽度一下就变到2毫秒了,从串口输出了命令ff010bff后,方波的宽度一下就变到0.5毫秒了。
我想请教各位大能,为什么我的程序不能象一些51的按键控制程序那样逐次地控制pwm方波的宽度?如何修改才能达到目的呢?请各位不吝赐教。
下面是我的程序:附件里是我的proteus仿真文件。
#include<reg52.h>
#include<math.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar Buffer =0; //从串口接收的数据
uint i=0,j,URTAReceivedCount=0,n=1;
uchar flag=0;
uchar data Tempdatatable[4],CommandDatatable[4];//数据包
sbit servo0=P0^0;
uchar serVal[2];
uint pwm[]={1382,1382,1382,1382,1382,1382,1382,1382}; //初始90度,(实际是1382.4,取整得1382)
uchar pwm_flag=0;
uint code ms0_5Con=461; //0.5ms计数 (实际是460.8,取整得461)
uint code ms2_5Con=2304; //2.5ms计数
/********************************************************************
* 名称 : Delay_1ms()
* 功能 : 延时子程序,延时时间为 1ms * x
* 输入 : x (延时一毫秒的个数)
* 输出 : 无
***********************************************************************/
void Delay_1ms(uint i)//1ms延时
{
uchar x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
/********************************************************************
* 名称 : Send_Data()
* 功能 : 向上位机传送字符
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Send_Data(uchar data type,uchar data cmd)
{
uchar data Buffer[4];
//构建数据包
uchar *p;
uint Send_Count=0;
p = Buffer;
Buffer[0]=0XFF;
Buffer[1]=type;
Buffer[2]=cmd;
Buffer[3]=0XFF;
while(1){
if(*p==0XFF){
Send_Count++; //0XFF标志统计位
}
SBUF = *p; //发送
while(!
ti) //如果发送完毕,硬件会置位TI,等待发送完毕
{
_nop_();
}
p++;
TI = 0;
if(Send_Count == 2) //当统计到两次出现0XFF,则认为一个数据包发送完毕,跳出循环
{
TI = 0;
break;
}
}
}
/********************************************************************
* 名称 : Com_Int()
* 功能 : 串口中断子函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Com_Int(void) interrupt 4
{
uchar temp;
ES=0; //关串口中断
RI=0; //软件清除接收中断
temp=SBUF;
if(temp==0XFF && URTAReceivedCount<2)
{
Tempdatatable[0]==0XFF; //包头
URTAReceivedCount++;
}
else
{
Tempdatatable[n]=temp;
n++;
}
if(URTAReceivedCount==2)//包尾
{
Tempdatatable[0]=0XFF;
Tempdatatable[3]=0XFF;
n=1;
URTAReceivedCount=0; //组包完毕
temp="";
//Send_Data(Tempdatatable[1],Tempdatatable[2]); //发送组成的数据包回去
}
CommandDatatable[0]=Tempdatatable[0];
CommandDatatable[1]=Tempdatatable[1];
CommandDatatable[2]=Tempdatatable[2];
CommandDatatable[3]=Tempdatatable[3];
ES=1;//开串口中断
}
/********************************************************************
* 名称 : Com_Init()
* 功能 : 串口初始化,晶振11.0592,波特率9600,使能了串口中断
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Com_Init(void)
{
TMOD |= 0x20;
PCON = 0x00;
SCON = 0x50;
TH1 = 0xFd; //设置波特率 9600
TL1 = 0xFd;
TR1 = 1; //启动定时器1
ES = 1; //开串口中断
EA = 1; //开总中断
IT0=0;
EX0=1;
}
/********************************************************************
* 功能 : 舵机PWM中断初始化
***********************************************************************/
void Timer0Init() {
//0度=0.5ms, 45度=1ms, 90度=1.5ms, 135度=2ms, 180度=2.5ms
//2.5 ms初始值 F700, (12n/11059200=2.5/1000, n=2304, X=65536-2304=63232 > F700)
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH0=-ms2_5Con>>8; //给定初值,17ms中断
TL0=-ms2_5Con;
EA=1; //总中断打开
ET0=1; //定时器0中断打开
TR0=1; //定时器0开关打开
}
/********************************************************************
* 功能 : 舵机PWM中断, //舵机控制函数 周期为20ms 一个循环20MS = 8*2.5ms
***********************************************************************/
void SteeringGear() interrupt 1 {
switch(pwm_flag)
{
case 1:
servo0=1;
TH0=-pwm[0]>>8;
TL0=-pwm[0];
break;
case 2:
servo0=0;
TH0=-(ms2_5Con-pwm[0])>>8;
TL0=-(ms2_5Con-pwm[0]);
break;
//...
default:
TH0=0xff;
TL0=0x80;
pwm_flag=0;
}
pwm_flag++;
}
void SteeringGearUp(uchar i) {
if(pwm
>ms0_5Con)
pwm=pwm-10;
}
void SteeringGearDown(uchar i) {
if(pwm<ms2_5Con)
pwm=pwm+10;
}
void main()
{
Delay_1ms(200);
Com_Init();//串口初始化
Timer0Init();//舵机初始化
while(1)
{
if(CommandDatatable[0]==0XFF && CommandDatatable[3]==0XFF){
switch (CommandDatatable[1]) //根据键值不同,执行不同的内容
{
case 0X01: //类型位0X01,表明是舵机数据包,进入舵机case
switch(CommandDatatable[2]) {
case 0X0A:
SteeringGearUp(0);
break;
case 0X0B:
SteeringGearDown(0);
break;
}
break;
default : TR0=0;TR2=0;
break;
}
}
}
}
-
-
-
driverictest01.rar
下载积分: 积分 -1 分
26.89 KB, 下载次数: 41, 下载积分: 积分 -1 分
要不你就收到一次,但是你会处理若干次,直到升到最大值或降到最小值
你想想看...
谢谢分享,楼主真是好人啊啊啊 啊啊
一周热门 更多>