这个应该是通过串口发送数据信息的,发送和接收在一根信号线上,手上没有现成的程序,你看看这个在其他网上的行不行,
最好根据手册自己写
#include <avr/ioh>
#include <util/delayh>
void InitUart0(void)
{
UCSR0A = 0x02; // 设置为倍速模式
UBRR0H = 0;
UBRR0L = 1;
UCSR0B = (1<<RXEN)|(1<<TXEN);// 接收器与发送器使能
UCSR0C = (3<<UCSZ0);
DDRE &= ~_BV(PE0); // 初始化RX 端口默认方向为输入
PORTE &= ~_BV(PE0); // 初始化RX 端口默认状态为高阻
DDRE |= _BV(PE1); // 初始化TX 端口默认方向为输出
PORTE |= _BV(PE1); // 初始化TX 端口默认状态为高电平
DDRA |= _BV(PA0); // 初始化使能端口状态方向为输出
PORTA &= ~_BV(PA0); // 初始化使能端口状态为RX 状态
DDRA |= _BV(PA1); // 初始化使能端口状态方向为输出
PORTA |= _BV(PA1); // 初始化使能端口状态方为TX 状态
}
void SendUart0Byte(unsigned char data)
{
while ( !( UCSR0A & (1<<UDRE)) );// 等待发送缓冲器为空
UDR0 = data;/ 将数据放入缓冲器,发送数据/
}
void SetServoLimit(unsigned char id, unsigned short int cw_limit, unsigned short int ccw_limit)
{
unsigned short int temp_ccw = 0; // 临时速度,用于进行方向判别
unsigned short int temp_cw = 0;
unsigned char temp_ccw_h = 0; // 待发送数据h 位
unsigned char temp_ccw_l = 0; // 待发送数据l 位
unsigned char temp_cw_h = 0;
unsigned char temp_cw_l = 0;
unsigned char temp_sum = 0; // 校验和寄存变量
if (ccw_limit > 1023)
{
temp_ccw = 1023; // 限制速度值在可用范围内
}
else
{
temp_ccw = ccw_limit;
}
if (cw_limit > 1023)
{
temp_cw = 1023;
}
else
{
temp_cw = cw_limit;
}
temp_ccw_h = (unsigned char)(temp_ccw >> 8);
temp_ccw_l = (unsigned char)temp_ccw; // 将16bit 数据拆为2个8bit 数据
temp_cw_h = (unsigned char)(temp_cw >> 8);
temp_cw_l = (unsigned char)temp_cw; // 将16bit 数据拆为2个8bit 数据
PORTA &= ~_BV(PA1);
PORTA |= _BV(PA0); // 使总线处于主机发送状态
UCSR0A |= (1<<TXC0); // 清除UART0写完成标志
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(id); // 发送id
SendUart0Byte(7); // 发送数据长度为参数长度+2,参数长度为3
SendUart0Byte(0x03); // 命令数据为“WRITE DATA”
SendUart0Byte(0x06); // 舵机控制寄存器首地址
SendUart0Byte(temp_cw_l); // 发送顺时针位置限制低位
SendUart0Byte(temp_cw_h); // 发送顺时针位置限制高位
SendUart0Byte(temp_ccw_l); // 发送逆时针位置限制低位
SendUart0Byte(temp_ccw_h); // 发送逆时针位置限制高位
temp_sum = id + 7 + 0x03 + 0x06 + temp_cw_l + temp_cw_h + temp_ccw_l + temp_ccw_h;
temp_sum = ~temp_sum; // 计算校验和
SendUart0Byte(temp_sum); // 发送校验和
while ( !( UCSR0A & (1<<TXC0)) ) // 等待发送完成
{ // (Waiting for finishing sending)
;
}
PORTA |= _BV(PA1);
PORTA &= ~_BV(PA0); // 使总线处于主机接收状态
_delay_ms(2); //送完成后,总线会被从机占用,反馈应答数据,所以进行延时
}
void SetServoPosition(unsigned char id, unsigned short int position, unsigned short int
velocity)
{
unsigned short int temp_velocity = 0; // 临时速度,用于进行方向判别
unsigned short int temp_position = 0;
unsigned char temp_velocity_h = 0; // 待发送数据h 位
unsigned char temp_velocity_l = 0; // 待发送数据l 位
unsigned char temp_position_h = 0;
unsigned char temp_position_l = 0;
unsigned char temp_sum = 0; // 校验和寄存变量
if (velocity > 1023)
{
temp_velocity = 1023; // 限制速度值在可用范围内
}
else
{
temp_velocity = velocity;
}
if (position > 1023)
{
temp_position = 1023;
}
else
{
temp_position = position;
}
temp_velocity_h = (unsigned char)(temp_velocity >> 8);
// 将16bit 数据拆为2个8bit 数据
temp_velocity_l = (unsigned char)temp_velocity;
temp_position_h = (unsigned char)(temp_position >> 8);
// 将16bit 数据拆为2个8bit 数据
temp_position_l = (unsigned char)temp_position;
PORTA &= ~_BV(PA1);
PORTA |= _BV(PA0); // 使总线处于主机发送状态
UCSR0A |= (1<<TXC0); // 清除UART0写完成标志
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(0xFF);
SendUart0Byte(id); // 发送id
SendUart0Byte(7); // 发送数据长度为参数长度+2,参数长度为3
SendUart0Byte(0x03); // 命令数据为“WRITE DATA”
SendUart0Byte(0x1E); // 舵机控制寄存器首地址
SendUart0Byte(temp_position_l); // 发送速度数据低位
SendUart0Byte(temp_position_h); // 发送速度数据高位
SendUart0Byte(temp_velocity_l); //发送位置低字节
SendUart0Byte(temp_velocity_h); // 发送位置高字节
temp_sum = id + 7 + 0x03 + 0x1E + temp_position_l + temp_position_h + temp_velocity_l +
temp_velocity_h;
temp_sum = ~temp_sum; // 计算校验和
SendUart0Byte(temp_sum); // 发送校验和 (Send the checksum)
while ( !( UCSR0A & (1<<TXC0)) ) // 等待发送完成
{ // (Waiting for finishing sending)
;
}
PORTA |= _BV(PA1);
PORTA &= ~_BV(PA0); // 使总线处于主机接收状态
_delay_ms(2); // 发送完成后,总线会被从机占用,反馈应答数据,所以进行延时
}
void SetServoVelocity(unsigned char id, signed short int velocity)
{
unsigned char temp_sign = 0; // 临时符号,用于进行方向判别
unsigned short int temp_velocity = 0; // 临时速度,用于进行方向判别
unsigned char temp_value_h = 0; // 待发送数据h 位
unsigned char temp_value_l = 0; // 待发送数据l 位
unsigned char temp_sum = 0; // 校验和寄存变量
if (velocity < 0)
{
temp_velocity = -velocity; // 如果为负数,则取绝对值
temp_sign = 1; // 设置负数符号标志
}
else
{
temp_velocity = velocity;
temp_sign = 0; // 设置正数符号标志
}
if (temp_velocity > 1023)
{
temp_velocity = 1023; // 限制速度值在可用范围内
}
temp_velocity |= (temp_sign << 10);
temp_value_h = (unsigned char)(temp_velocity >> 8);
// 将16bit 数据拆为2个8bit 数据
temp_value_l = (unsigned char)temp_velocity;
PORTA &= ~_BV(PA1);
PORTA |= _BV(PA0); // 使总线处于主机发送状态
UCSR0A |= (1<<TXC0); // 清除UART0写完成标志
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(id); // 发送id
SendUart0Byte(5); // 发送数据长度为参数长度+2,参数长度为3
SendUart0Byte(0x03); // 命令数据为“WRITE DATA”
SendUart0Byte(0x20); // 舵机控制寄存器首地址
SendUart0Byte(temp_value_l); // 发送速度数据低位
SendUart0Byte(temp_value_h); // 发送速度数据高位
temp_sum = id + 5 + 0x03 + 0x20 + temp_value_l + temp_value_h;
temp_sum = ~temp_sum; // 计算校验和
SendUart0Byte(temp_sum); // 发送校验和
while ( !( UCSR0A & (1<<TXC0)) ) // 等待发送完成
{
;
}
PORTA |= _BV(PA1);
PORTA &= ~_BV(PA0); // 使总线处于主机接收状态
_delay_ms(2); // 发送完成后,总线会被从机占用,反馈应答数据,所以进行延时
}
int main(void)
{
InitUart0();
SetServoLimit(2,0,1023);
while(1)
{
_delay_ms(1000); //延时1s
SetServoPosition(2, 1000, 500); //控制舵机以500的速度运动到1000的位置
_delay_ms(1000); //延时1s
SetServoPosition(2, 200, 100); //控制舵机以100的速度运动到200的位置
}
}
这是控制180度舵机转到90度的程序,比较简单!library ieee;
use ieeestd_logic_1164all;
use ieeestd_logic_arithall;
use ieeestd_logic_unsignedall;entity yan is
port(clk:in std_logic;
po:out std_logic);
end yan;architecture zheng of yan is
signal co:integer range 0 to 1000000;
begin
process(clk)
if clk'event and clk='1' then
co<=co+1;
if co<75000 then
po<='1';
else
po<='0';
end if;
end if;
end process;
end zheng;
#include<reg52h>typedef unsigned int uint;typedef unsigned char uchar;sbit pwm=P0^3;//输出PWM信号uchar count=0;uint pwm_value=1500;//初值为15msuint value[]={1500,1000,1500,2000,1500};//void delay_ms(uint x){uint i;while(x--)for(i=0;i<125;i++);}void InitTimer(void){TMOD=0x11;//开定时器0,1TH0=-20000/256;//定时20MS,20MS为一个周期TL0=-20000%256;TH1=-1500/256;//定时15MS,这时舵机处于0度TL1=-1500%256;EA=1;//开总断TR0=1;//开定时器0ET0=1;TR1=1;//开定时器1ET1=1;}void timer0(void) interrupt 1//定时器0中断函数{pwm=1;TH0=-20000/256;TL0=-20000%256;TR1=1;count++;}void timer1(void) interrupt 3//定时器1中断函数{pwm=0;TH1=-pwm_value/256;TL1=-pwm_value%256;TR1=0;}void main(void)//主函数{uchar i;InitTimer();pwm_value=1500;while(1){for(i=0;i<5;i++){pwm_value=value[i];//通过数组就可以改变舵机的转角度delay_ms(1000);}}}
看一下舵机控制器主芯片旁边的双排针,使用RS232来控制的时候是有条线帽的,您要使用Arduino控制需要将条线帽拆除,用四根杜邦线连接内侧的排针和UNO控制器,连接之前将程序导入到UNO控制器中,接线顺序为:TX-RX,RX-TX,+接电源正,-接GND然后给舵机供电,就可以使用UNO控制器来控制32路舵机控制器了。
#include<reg52h>
#define uint unsigned int
#define uchar unsigned char
uchar k; //k表示总时间 因为定时器中断要用到k,所以放在程序头
sbit PWM1=P1^0;
sbit key1=P3^7; //舵机启动开关
void init()
{
TMOD=0X01;
TH0=(65536-92)/256;
TL0=(65536-92)%256;
EA=1;
ET0=1;
TR0=1;
}
void jiman20() //51模拟PWM波函数
{
static uchar flag=0,j=0; //flag当做PWM高电平变宽/变窄的标志;
//j表示高电平持续的时间;k表示总时间因为重复调用该函数
if(k==200) //第一步:判断计时满20ms
{
k=0; //k归零
if(flag==0) //标志为0时,高电平标志增加
j++;
else //标志为1时,高电平标志减小
j--;
if(j>=25) //当j=25时,高电平持续时间为25ms,此时角度为180
flag=1; //必须改变宽/窄标志。
if(j<=0) //当j=0时,高电平持续时间为0ms,此时角度为0
flag=0; //必须改变宽/窄标志。
}
if(k<j) //第二步:在20ms判断结束的基础上,输出PWM
PWM1=1; //因为每20ms,k就归0所以能通过判断k<j,输出高电平
else PWM1=0;
}
void main()
{
uint i=60000;
init();
while(i--) //一开机就让舵机有一个转动
{
jiman20();
}
while(1)
{
while(key1==0) //当开关打开,启动定时器,进入转动程序并循环
{
TR0=1;
jiman20();
}
TR0=0; //当开关关闭,关闭定时器,舵机保持最末时刻状
}
}
void timer() interrupt 1 //定时器计时01ms,即模拟PWM是以01s为分度,
//高电平逐渐增加/减少
{
TR0=0;
TH0=(65536-92)/256;
TL0=(65536-92)%256;
TR0=1;
k++;
}
实测能用,不谢!
20ms为舵机周期,一个周期可以同时控制8个舵机,20/25=8
用定时器产生脉冲,两个定时器T0,T1,82,同时可以控制16个舵机,
以下是用按键控制一个舵机的转动,你可以参考以下程序,多设个io口,在switch函数中的 条件语句中加各个io口脉宽,以下程序中的例如:case 0中的if可以多加几个io控制就可以同时控制多个了,程序前面也可以开定时器T0,以下就只开T1。懒得改以下程序,你参考下就明白了,原理明白就好搞,以下程序很基础,很简单明了了。
#include <reg52h>
#define Stop 0 //宏定义,停止
#define Left 1 //宏定义,左转
#define Right 2 //宏定义,右转
sbit ControlPort = P1^1; //舵机信号端口
sbit KeyLeft = P3^2; //左转按键端口
sbit KeyRight = P3^3; //右转按键端口
sbit KeyStop = P1^3; //归位按键端口
unsigned char TimeOutCounter = 0,LeftOrRight = 0; //TimeOutCounter:定时器溢出计数 LeftOrRight:舵机左右旋转标志
void InitialTimer ( )
{
TMOD=0x10; //定时/计数器1工作于方式1
TH1 = ( 65535 -87 ) / 256; //01ms
TL1 = ( 65535 - 87 ) % 256;
EA=1; //开总中断
ET1=1; //允许定时/计数器1 中断
TR1=1; //启动定时/计数器1 中断
}
ControlLeftOrRight ( ) //控制舵机函数
{
if( KeyStop == 0 )
{
while ( !KeyStop ); //使标志等于Stop(0),在中断函数中将用到
LeftOrRight = Stop;
}
if( KeyLeft == 0 )
{
while ( !KeyLeft ); //使标志等于Left(1),在中断函数中将用到
LeftOrRight = Left;
}
if( KeyRight == 0 )
{
while ( !KeyRight ); //使标志等于Right(2),在中断函数中将用到
LeftOrRight = Right;
}
}
main ( ) //主函数
{
InitialTimer();
for(;;)
{
ControlLeftOrRight();
}
}
void Timer1 ( void ) interrupt 3 //定时器中断函数
{
TH1 = ( 65535 - 87 ) / 256;
TL1 = ( 65535 - 87 ) % 256;
TimeOutCounter ++;
switch ( LeftOrRight )
{
case 0 : //为0时,舵机归位,脉宽15ms
{
if( TimeOutCounter <= 15 )
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 1 : //为1时,舵机左转,脉宽1ms(理论值),实际可以调试得出
{
if( TimeOutCounter <= 10)
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 2 : //为2时,舵机右转,脉宽2ms(理论值),实际可以调试得出
{
if( TimeOutCounter <=22 )
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
default : break;
}
if( TimeOutCounter == 200 ) //周期20ms(理论值),比较可靠,最好不要修改
{
TimeOutCounter = 0;
}
}
以上就是关于求stm32控制四自由度舵机的程序全部的内容,包括:求stm32控制四自由度舵机的程序、求基于VHDL的控制舵机程序、急求51单片机控制舵机C语言程序,舵机可以根据设定旋转任意角度!急求啊,大神帮帮忙!非常感谢!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)