求stm32控制四自由度舵机的程序

求stm32控制四自由度舵机的程序,第1张

这个应该是通过串口发送数据信息的,发送和接收在一根信号线上,手上没有现成的程序,你看看这个在其他网上的行不行,

最好根据手册自己写

#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语言程序,舵机可以根据设定旋转任意角度!急求啊,大神帮帮忙!非常感谢!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10626274.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-10
下一篇 2023-05-10

发表评论

登录后才能评论

评论列表(0条)

保存