利用STC89C52控制ROS中的海龟

该博客介绍了如何通过STC89C52单片机实现串口通信,使用C语言编程并设置波特率9600。在Ubuntu上利用cutecom进行串口调试,并通过Python3编写ROS程序处理接收到的数据,控制机器人的运动。当接收到特定按键信号时,机器人执行相应动作,如前进、后退、左转、右转。同时,给出了ROS节点的launch文件配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现过程:
1、单片机程序编序(C语言)
STC89C52单片机 晶振频率11.0592MHz

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit led =P1^0;  // 发送指示灯
sbit s1 = P3^4;  // 左转
sbit s2 = P3^5;  // 前进
sbit s3 = P3^6;  // 右转
sbit s4 = P3^7;  // 停止
uchar num='S';   // 初始状态为停止 STOP
void delay(uint x)   // 键盘消抖
{	
	uint i,k;
	for(i=0;i<x;i++)
		for(k=0;k<1000;k++);
}
void init()
{
	TMOD=0x20;	 //设定T1定时器工作方式2
	TH1=0xfd;    //波特率9600
	TL1=0xfd;	 //波特率9600
	TR1=1;		 //启动定时器1
	SM0=0;		 //串口工作方式1  八位异步串行通信
	SM1=1;		 //一帧数据结构为一个起始位,八个数据位,一个停止位 
	REN=1;		 //允许串口接收
	EA=1;		 //开总中断
	ES=1;		 //开串口中断
	PCON=0x00;	 //SMOD=1	    要获得9600波特率  OXFD对应SMOD值为0 0XFA对应SMOD值为1
}

void key()
{
	if(s1 == 0)
	{
		delay(5);      // 消抖
		if(s1 == 0)
		{	
			num = 'L';
		  	while(!s1);   // 松手检测
		}
	}

	if(s2 == 0)
	{
		delay(5);          // 消抖
		if(s2 == 0)
		{	
			num = 'Q';
		  	while(!s2);     // 松手检测
		}
	}

	if(s3 == 0)
	{
		delay(5);      // 消抖
		if(s3 == 0)
		{	
			num = 'R';
		  	while(!s3);      // 松手检测
		}
	}
	if(s4 == 0)
	{
		delay(5);     // 消抖
		if(s4 == 0)
		{	
			num = 'S';
		  	while(!s4);     // 松手检测
		}
	}
}
void main()
{
	init();
	while(1)
	{
		key();   // 键盘检测
		ES=0;    // 关闭串口中断
		SBUF=num;   // 将发送数据写入缓冲区
		while(!TI);  // 等待发送完成
		TI=0;       // 清除发送标志位
		ES=1;       // 开启串口中断
		led = ~led; // led闪烁
		delay(100);  // 发送间隔
	}
}

2、ubuntu20.04 中的串口调试助手
串口调试助手使用的是:cutecom
	波特率9600 数据位8位   停止位1位
sudo cutecom   
3、串口加权限
sudo chmod 666 /dev/ttyUSB0
4、python3语言编写ROS程序
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
import serial
from geometry_msgs.msg import Twist

if __name__ == '__main__':

    #2.初始化 ROS 节点:命名(唯一)
    rospy.init_node("serial")

    ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=0.2)
    # 打开前先关闭串口
    ser.close()
    # 打开串口
    ser.open()

    if ser.is_open:

        print("......串口已经打开!")

    else:

        print("......串口打开失败!")

    pub = rospy.Publisher("/turtle1/cmd_vel",Twist,queue_size=10)

    twist = Twist()

    rate = rospy.Rate(2)

    while not rospy.is_shutdown():

        rate.sleep()

        try:
            recv = ser.readline()

            r = str(recv)

            r_l = list(r[2])
            print(r_l)
            if r_l[0] == 'L':
                twist.linear.x = 0
                twist.angular.z = 0.5
            if r_l[0] == 'Q':
                twist.linear.x = 1
                twist.angular.z = 0
            if r_l[0] == 'R':
                twist.linear.x = 0
                twist.angular.z = -0.5
            if r_l[0] == 'S':
                twist.linear.x = 0
                twist.angular.z = 0

            print(twist.linear.x)
            print(twist.angular.z)

            pub.publish(twist)

        except (OSError, TypeError) as reason:
            print('错误的原因是:', str(reason))
            # 关闭串口
            ser.close()
            print("......串口已经关闭。")
    
    ser.close()
    print("......串口已经关闭。")

5、launch文件编写
<launch>
    <node pkg = "turtlesim" type = "turtlesim_node" name = "wugui"/>
    <node pkg = "turele_51" type = "com_turtle.py" name = "kongzhi"/>
</launch>
### STC89C52 单片机ROS 的通信方法 STC89C52 是一款经典的 8051 架构单片机,而 ROS(Robot Operating System)是一种用于机器人开发的开源框架。两者之间的通信可以通过串口或其他接口实现。 #### 1. 硬件连接方式 通常情况下,STC89C52ROS 主要通过 UART(通用异步收发传输器)进行数据交换。UART 接口可以将 TTL 或 RS-232 信号转换为可被计算机识别的数据流。具体来说: - **硬件模块选择**:由于 STC89C52 不具备 USB 功能,因此需要借助外部芯片(如 CH340G、CP2102 或 FT232RL),将其 UART 转换为 USB 接口[^1]。 - **接线说明**: - 将 STC89C52 的 TXD 引脚连接到 USB-TTL 模块的 RXD 引脚; - 将 STC89C52 的 RXD 引脚连接到 USB-TTL 模块的 TXD 引脚; - GND 进行共地处理; #### 2. 软件配置 ##### (a) STC89C52 编程部分 在单片机端编写程序以发送或接收数据。以下是基于 C 语言的一个简单示例代码片段,展示如何初始化串口并发送字符给上位机: ```c #include <reg52.h> sbit LED = P1^0; // 定义LED灯控制引脚 void delay(unsigned int i); // 延时函数声明 void Uart_Init(); // 初始化串口中断子函数声明 unsigned char code table[]="Hello,ROS!"; void main() { unsigned char i=0; Uart_Init(); while(1){ SBUF=table[i]; // 发送缓冲区赋值 while(TI==0); // 查询发送完成标志位TI TI=0; // 清除发送中断标志位 if(++i >= sizeof(table)-1){ // 判断字符串是否发送完毕 i=0; } delay(0xFFFF); } } // 中断初始化设置波特率等参数 void Uart_Init(){ TMOD |= 0x20; // 设置定时器模式2 TH1 = 0xFD; // 波特率为9600bps @11.0592MHz晶振频率下计算得到TH1初值 TR1 = 1; // 启动T1计数器工作 ES = 1; // 开启串口中断允许开关ES置1 EA = 1; // 打开总中断EA置1 } ``` 上述代码实现了向 PC 上运行的 ROS 节点发送固定消息的功能[^2]。 ##### (b) ROS 配置节点 创建一个新的 Python 脚本作为订阅者/发布者来监听来自 MCU 的信息或者反过来操作设备动作反馈至嵌入式系统中去执行相应命令逻辑流程图如下所示: ```python #!/usr/bin/env python import rospy from std_msgs.msg import String def callback(data): rospy.loginfo(rospy.get_caller_id() + ' I heard %s', data.data) def listener(): # In ROS, nodes are uniquely named. rospy.init_node('stc_listener', anonymous=True) rospy.Subscriber('chatter', String, callback) # spin() simply keeps python from exiting until this node is stopped rospy.spin() if __name__ == '__main__': try: listener() except Exception as e: pass ``` 此段落描述了一个基本的 ROS 订阅模型,其中 `listener` 函数负责启动一个名为 stc_listener 的新进程实例,并持续等待主题 chatter 下的新消息到达事件触发回调机制打印日志输出结果[^3]。 #### 3. 数据协议设计 为了使双方能够理解彼此传递过来的内容含义明确无误,在实际项目应用过程中往往还需要定义一套专属的应用层通讯规约标准比如 JSON/XML 格式的报文体结构或者是自定义二进制编码方案等等形式不一而足取决于具体需求场景考量因素众多这里不做详述仅提供思路方向供参考学习之用而已[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhaojieming1990

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值