STM32
直播中

孔妞妞

11年用户 481经验值
私信 关注
[问答]

如何完成外部硬件触发装置?

如何完成外部硬件触发装置?

回帖(1)

张琼

2021-11-11 11:23:15
  1.任务

  1)学习现有雷达同步板,测试现有雷达同步板精度
2)STM32实现用串口接收四位数,接收到瞬间一发出高电平,并且根据数字大小设置高电平持续时间
3)使用boost::asio库在ubuntu系统上写一个周期性向串口发送信息的类
  2.环境 & 工具

  STM32F103RCT6
串口USB转接线
上面两个东西要看原理图,硬件连接和代码管脚选择需要它们
  1) 同步板
STM32F103RCT6 和 扩展板
示波器RIGOL-DS2072A
  2)windows
STM32CubeMX
Keil5
XCOM
FlyMCU
  3)ubuntu16.04
ROS kinetic
cutecom
  3.准备工作

  3.1 同步板部分

  读已有代码,了解大致功能
提供的说明与测试不符,所以先用万用表将每个管脚的定义分清楚
  3.2 STM32部分

  STM32CubeMX新建项目,进行配置:
  


  • 一个输出管脚
  • 一组串口USART
  • 时钟相关配置

  生成代码,用keil5打开项目
  3.3 ubuntu部分

  创建工作空间,创建包
vscode配置
以上实习记录(一)中有记录
  4.代码

  4.1 同步板部分

  无
  4.2 STM32部分

4.2 STM32部分
//第一处代码
/* USER CODE BEGIN 2 */
 //测试提示用
  //HAL_UART_Transmit(&huart1, (uint8_t *)"初始化成功", 12, 0xFFFF);
/* USER CODE END 2 */


//第二处代码
/* USER CODE END WHILE */
    char rx_message[RXSIZE] = {0};
    uint16_t rx_int = 0;


    /* USER CODE END 2 */


    HAL_UART_Receive(&huart1, (uint8_t *)&rx_message, RXSIZE, 0xffff);
    //HAL_UART_Transmit(&huart1, (uint8_t *)&rx_message, RXSIZE, 0xffff);
    while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);


    for (int i = 0; i < RXSIZE; i++) {
      rx_int = rx_int + ((int)rx_message - 48) * pow(10, RXSIZE - i - 1);
    }
   
    //HAL_UART_Transmit(&huart1, (uint8_t *)&rx_int, RXSIZE, 0xffff);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
    HAL_Delay(rx_int);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);


    /* USER CODE BEGIN 3 */


4.3 ubuntu部分
//main.cpp
#include "writer_handler.h"
#include


int main(int argc, char* argv[])
{
  std::cout << "Program Start ..." << std::endl;
  xxxx::SerialPortWriter my_sp("/dev/ttyUSB0", 115200);
  while (1)
  {
    try
    {
      my_sp.serialWrite("0010");
    }
    catch (std::exception& err)
    {
      std::cout << err.what() << std::endl;
    }
    boost::this_thread::sleep(boost::posix_time::milliseconds(200));
  }


  return 0;
}


//类.h
#ifndef WRITER_HANDLER_H
#define WRITER_HANDLER_H


#include
#include
#include


typedef std::string any_type;


namespace xxxx
{
class SerialPortWriter
{
public:
  SerialPortWriter(const any_type& port_name, const u_int32_t baud_rate);


  ~SerialPortWriter();


  void serialWrite(const any_type data);


  void serialRead();


  void handleCall();


private:
  boost::asio::io_service my_ios_;


  boost::asio::serial_port* p_serial_port_;


  boost::system::error_code ec_;
};
}  // namespace xxxx






#endif


//类.cpp
#include "writer_handler.h"


#define MSGSIZE 4


namespace xxxx
{
SerialPortWriter::SerialPortWriter(const any_type& port_name, const u_int32_t baud_rate) : p_serial_port_(NULL)
{
  p_serial_port_ = new boost::asio::serial_port(my_ios_);
  p_serial_port_->open(port_name, ec_);
  p_serial_port_->set_option(boost::asio::serial_port::baud_rate(baud_rate), ec_);
  p_serial_port_->set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::none), ec_);
  p_serial_port_->set_option(boost::asio::serial_port::parity(boost::asio::serial_port::parity::none), ec_);
  p_serial_port_->set_option(boost::asio::serial_port::stop_bits(boost::asio::serial_port::stop_bits::one), ec_);
  p_serial_port_->set_option(boost::asio::serial_port::character_size(8), ec_);
}


SerialPortWriter::~SerialPortWriter()
{
  if (p_serial_port_)
  {
    delete p_serial_port_;
  }
}


void SerialPortWriter::serialWrite(const any_type data)
{
  p_serial_port_->write_some(boost::asio::buffer(data), ec_);
  std::cout << "nwrite: " << data << std::endl;
  handleCall();
}


void SerialPortWriter::serialRead()
{
  char v[MSGSIZE];
  p_serial_port_->read_some(boost::asio::buffer(v, MSGSIZE), ec_);
  std::cout << "nread: " << v << std::endl;
}


void SerialPortWriter::handleCall()
{
  my_ios_.run();
}


}  // namespace xxxx




//cmakelist
//直接用自动生成的提示文档修改的,其中前面有#的都是无效部分
cmake_minimum_required(VERSION 3.0.2)
project(serial_writer)


## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)


## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
)


## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)




## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()


################################################
## Declare ROS messages, services and actions ##
################################################


## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)


## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )


## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )


## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )


## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )


################################################
## Declare ROS dynamic reconfigure parameters ##
################################################


## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed


## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )


###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES serial_writer
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)


###########
## Build ##
###########


## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
include
  ${catkin_INCLUDE_DIRS}
)


## Declare a C++ library
add_library(writer_handler
   src/writer_handler.cpp
   include/writer_handler.h
)


## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(
  writer_handler
  ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(
  serial_writer_main
  src/serial_writer_main.cpp)


## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")








## Specify libraries to link a library or executable target against
target_link_libraries(
  serial_writer_main
  writer_handler
  ${catkin_LIBRARIES}
)


#############
## Install ##
#############


# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html


## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )


## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )


## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )


## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )


## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )


#############
## Testing ##
#############


## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_serial_writer.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()


## Add folders to be run by python nosetests
# catkin_add_nosetests(test)


————————————————
版权声明:本文为CSDN博主「o66oCZRo99o」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/o66oCZRo99o/article/details/107753381
  5.运行测试

  5.1 同步板部分

  [tr]周期个数startend平均周期平均误差[/tr]
第一组50-42.87s7.123s999.86111ms-0.13889ms
第二组50-47.88s2.110s999.84615ms-0.15385ms
第三组50-38.07s11.92s999.80000ms-0.20000ms
第四组50-49.87s124.1ms999.88200ms-0.11800ms
第五组50-41.09s8.898s999.76000ms-0.24000ms
以上五组平均误差为:-0.170418ms
  

  • 发现该示波器确实存在精度误差,难以测得需要精度的正确值
  • 故找硬件组帮忙测试,超大示波器,据说三十万一台,能连鼠标键盘,还能触屏
  • 发现之前测试成了 TTL-DATA 端口,应该测试的是 TTL-PPS 端口,两者的最大波形周期是相同的,但TTL-DATA端口的每个大波形上又许多大小不等的小方波,是时间戳信息
  • 并且还发现,GPS接上后,同步板的PPS输出会在一定时间时突然出现一个下降沿,可能是单片机时钟自动归位造成的现象

  5.2 STM32部分

  用串口USB转接线连接STM32和电脑
  用FlyMcu用hex文件将项目编译进STM32
  用XCOM向串口发送信息,看返回信息是否正确,并且用示波器检查输出管脚的波形
  5.3 ubuntu部分

  用命令给USB开启权限(在这里卡了好久,一直以为代码有问题,一定要检查硬件啊,哭~
  #查看连接的USB转串口 ls -l /dev/ttyUSB* #u***给权限 sudo chmod 777 /dev/ttyUSB0   用串口USB转接线插入电脑,自己的RX和TX接上
  编译运行串口发送程序,观察返回值是否正确
  或者两根转接线把两台电脑连接起来,另一台用cutecom观察返回值
  5.3  综合测试

  用串口USB转接线连接STM32和电脑
  编译运行串口发送程序,修改数值多测几组
  用示波器检测输出管脚波形
    结语:开始工作之前一定要把需求确定清楚,方案交流清楚,花了大半天研究怎么用串口中断接收不定长信息,前辈过来看直接表示,外部触发实际使用中信息一定是定长定类型的,这么做没有必要。好吧,又绕路了,方向确实非常重要,不然容易白做功。硬件和软件一样需要检查,运行有问题两者的原因都有可能。之前还是孤陋寡闻了,boost库第一次使用,临时学习也花了一些时间。
  注:本文为自用实习记录
举报

更多回帖

×
20
完善资料,
赚取积分