文章目录

  • 一、风速计硬件连接部分
    • 1.1 485->TTL模块
    • 1.2 485风速计
  • 二、设备调试常见问题分享
  • 三、采用串口阻塞来发送接收
    • 3.1 STM32CubeMX设备配置
    • 3.2 Keil代码介绍(阻塞接收)
  • 四、采用串口DMA实现发送接收
    • 4.1 STM32CubeMX+DMA介绍
    • 4.2 Keil + USART + DMA模式
  • 总结

因为自己做毕业设计的需要,要调试风速计,因为第一次接触,特此来记录一下,文章不妥之处可在下面评论区,或者发送邮件至2802433362@qq.com,我会认真听取意见和建议的。


一、风速计硬件连接部分

对于485通信协议,我的理解是利用双绞线的差分信号来传递信息。如果对485通信协议感兴趣,我觉着可以去看《创客学院》的武老师讲的5种常见通信协议,我感觉老师讲的很清楚,小破站好像也有资源,不过好像不全,作为一名大学生嘛,找资源毕竟是一种基本技能,大家可自由发挥。
因为我们主要的目的是将传感器用起来,所以这篇主要是以应用配置为主,下面开始!!!

1.1 485->TTL模块

我们在学习STM32单片机串口部分的时候,我们要想把数据发送到串口调试助手上需要借助TTL->USB模块,同样在做485通信部分也需要一款485转TTL芯片,大家去淘宝买一下就好了,这个是我用到的芯片,因为我是需要把这个模块放到我的PCB板上的,所以买了485->TTL的。

485模块
引脚图
-----

我们在使用的时候只需要左侧的(2)、(3)、(4)、(5),这个我们用的比较多很容易做,在右侧的部分我们只需用到(7)、(8),即A、B两相信号线
黄色的线连接B相,绿色的线连接A相

1.2 485风速计

我使用的是这款的风速计,具体的资料可以参考下面的这个连接,有具体的一些通信协议

https://wiki.dfrobot.com.cn/SKU_SEN0483_RS485_Wind_Speed_Transmitter

整体连接线如下图所示:

从图中我们可以看到一下几个器件:
(1)电源适配器:因为风速计本身需要7~24V供电,所以需要另外一路电源来提供;
(2)风速计:这个是我们需要调节的传感器,他的输出口是有4根线的,如上图所示所示,1路电源线,1对信号线;
(3)风速计电源线和信号线:此处电源线需要跟适配器相连,信号线A、B两相直接接入485模块即可,不需任何供地,因为485通信是根据差分信号来传输信息的;
(4)485->TTL模块:上面已经介绍,不再赘述;
(5)ST-LINK: 烧录程序和调试使用;
(6)核心板:STM32F103C8T6;
(7)TTL->USB模块: 将接收的数据发送到串口。

此处推荐一款很好用的串口软件:微软自带的“串口调试助手”,他不仅界面简洁,而且后面还可以实现绘图的功能

二、设备调试常见问题分享

  • 在开始之前,有几个特别好玩的事情想和大家分享一下:

1. 本来是485通信,你光讲串口干嘛,我要听485通信?
(a)其实是这样子的,485通信和串口就应用层面来说,485传输距离更远,信号抗干扰能力更强,但这只是他的硬件特征,485通信和串口的区别其实就是电平不太一样,需要进行一下电平转换,但是这部分的工作,485->TTL的模块已经完成了,而且我们也发现上面我介绍的那个模组,一侧是485的通信口,一侧是串口的RX和TX。所以在软件层面上,他们是完全一样的,调试485通信设备其实跟调试串口设备完全一样
(b)相信大家之间都有过调串口设备,例如蓝牙的AT指令集的经验(当然没经验也没关系,因为后面我会细讲)。基本上是通过串口发送一个指令,然后设备会返回给你一组数据,然后你对这组数据进行提取处理即可。

2. 我看你好像用了两个串口,之前我学习过串口重定向,一般分享的串口重定向都是只能一个串口,但是我想每个串口都能用printf()可不可以?
(a)当然是可以的啊,之前我们都是直接从网上荡下那段熟悉的代码,然后就可实现一个串口的重定向了,多个串口也是一样的,不过稍微复杂一点的是需要构造两个函数,我们只需要在usart.c文件中嵌入一下代码即可,这样我们既可以利用uart1_printf()函数和uart2_printf()函数显示调用,代码可参考后面,目前只是提一下。

3. 我不知道我程序写的对不对,但是我想先看下我的485设备是否可以正常工作可以吗
这个是可以的,我们只需要在“串口调试助手“”中发送可以让设备回应的数据帧就好了,以风速计为例。我们发送数据查询帧,之后就会收到设备数据应答帧,我们想要的风速值也包含在其中,我们只需要读取就行。
注意:我们发送数据是16进制的,不是字符串类型的,后面在写代码的时候也要注意

我们可以用串口调试助手简单看一下我们的485设备是否正常工作
需要注意(1)波特率是否和设备的一致;(2)我们接收区的设置要设置为16进制显示;(3)发送区也要设置成16进制发送。

三、采用串口阻塞来发送接收

这次共使用了2个串口,USART1(PA9、PA10)和USART2(PA2、PA3)。我们想要USART2来负责和485设备进行通信,USAR1T来和电脑进行串口通信。

3.1 STM32CubeMX设备配置

(1)我们先设置为“SW”调试模式;

(2)下面我们选择外部晶振模式;

(3)我们设置USART1,模式设置为异步,因为USART1用来和电脑通信,所以我们波特率可以选择为115200;

(4)对于USART2, 模式也同理配置为异步, 因为此串口是用来和485设备进行通信,所以波特率要和设备固有的9600一值

(5)为了观察是否成功发送数据,我们可以打开一个指示灯,PC13(核心板自带的灯对应的GPIO脚)

(6)我们设置时钟树:(一定要注意我们单片机的外部晶振是否为8M,需要根据对应的参数进行修改,有些单片机不太一样,要不然后面的所有时钟全是错的)。我们直接将时钟设置为最快,72M


这样的话,我们的STM32CubeMX就配置完成了。

3.2 Keil代码介绍(阻塞接收)

在主函数的while循环里面添加以下代码即可,一定要注意发送的不是字符串数据而是16进制数据
我们可以在usart.c文件中添加以下代码就可以实现多个串口的重定向了。

#include "stdarg.h"
#include "string.h"
#include "stdio.h"
#define TXBUF_SIZE_MAX 100
void uart1_printf(const char *format, ...)
{va_list args;uint32_t length;uint8_t txbuf[TXBUF_SIZE_MAX] = {0};va_start(args, format);length = vsnprintf((char *)txbuf, sizeof(txbuf), (char *)format, args);va_end(args);HAL_UART_Transmit(&huart1, (uint8_t *)txbuf, length, HAL_MAX_DELAY);memset(txbuf, 0, TXBUF_SIZE_MAX);
}void uart2_printf(const char *format, ...)
{va_list args;uint32_t length;uint8_t txbuf[TXBUF_SIZE_MAX] = {0};va_start(args, format);length = vsnprintf((char *)txbuf, sizeof(txbuf), (char *)format, args);va_end(args);HAL_UART_Transmit(&huart2, (uint8_t *)txbuf, length, HAL_MAX_DELAY);memset(txbuf, 0, TXBUF_SIZE_MAX);
}

在“main.c”文件中添加以下代码,可以实现基础代码收发,但是这种方式是比较占用CPU资源的。

unsigned char ReceiveBuff[BUFFERSIZE];        //接收缓冲区
double wind_speed=0;
uart2_printf("%c%c%c%c%c%c%c%c", 0x02,0x03,0x00,0x00,0x00,0x01,0x84,0x39);   //给设备发送16进制问询帧
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);                                       //指示灯电平反转
HAL_UART_Receive(&huart2, ReceiveBuff, 8, 100);                              //单片机接收数据帧,读取设备接收帧的前8个数据,保存在ReceiveBuff数组里面
wind_speed = (ReceiveBuff[3]*256 + ReceiveBuff[4])/10.0;                     //此处没有信息校验,直接按公式将有用数据读出
uart1_printf("wind_speed:%.3f\r\n", wind_speed);                             //将读取到的信息发送至电脑显示
for(int k = 0; k < 8 ; k++) //清空接收缓存区                                 //将数组数据清空ReceiveBuff[k]=0;
HAL_Delay(500);

通过阻塞方式来实现串口收发比较占用时间。对于一些传感器较多或者其他程序处理方面较多的项目,我比较推荐使用DMA的方式,而且最好我们能有一套数据自己的高效率的串口收发模板,这样可以大大提高我们之后的代码开发效率。

四、采用串口DMA实现发送接收

本次实验采用的是串口DMA方式来实现不定长数据的收发,并形成了一个比较简单的模板。

这部分参考的是小破站上的一个教学视频,感觉蛮好的:
https://www.bilibili.com/video/BV1vv411W7AU?spm_id_from=333.337.search-card.all.click

4.1 STM32CubeMX+DMA介绍

(1)打开STM32CubeMX,对于前面的SYS、RCC配置过程都是一样,只不过在串口配置的部分是有区别的,首先我们来配置串口1

(2)必须要打开串口1的中断,因为我们想用的是串口空闲中断

(3)串口1的波特率跟设备的波特率保持一致就好了,这里为9600.

(4)因为串口2只是用来和电脑来进行串口通信,所有只要设置成异步模式就好了,其余不需要设置,默认即可。

(5)剩下的跟前面的完全一样,点击生成工程即可。

4.2 Keil + USART + DMA模式

(1)在“main.c”中导入这些初始变量的定义

#define BUFFERSIZE 100                //接收的数据帧长度,本次其实只用了10位以内,为了通用性考虑,可以设置得大一些
uint8_t ReceiveBuff[BUFFERSIZE];      //定义接收数据存放的数组
uint8_t recv_end_flag = 0,Rx_len=0;   //成功接收标志位;接收数据的长度
extern DMA_HandleTypeDef hdma_usart1_rx;
double wind_speed=0;

(2)在“main.c”文件中添加应用程序,需要将中断和DMA初始化。

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);  //开启串口空闲中断
HAL_UART_Receive_DMA(&huart1, ReceiveBuff, BUFFERSIZE);//开始让DMA接收一次

(3)下面我们开始编写串口中断程序,我们需要在“stm32f1xx_it.c”文件中添加:

我们需要将在”main.c“文件中定义的变量再导入一下:

#define BUFFERSIZE 100
extern uint8_t ReceiveBuff[BUFFERSIZE];
extern uint8_t recv_end_flag,Rx_len;

然后将这个文件拉到最下面,可以找到这个函数,添加下面的代码:

uint32_t temp;if(USART1 == huart1.Instance)//判断是否为串口1中断{      if(RESET != __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))//如果为串口1{__HAL_UART_CLEAR_IDLEFLAG(&huart1);     //清除中断标志HAL_UART_DMAStop(&huart1);              //停止DMA接收temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);//获取DMA当前还有多少未填充Rx_len=  BUFFERSIZE - temp; //计算串口接收到的数据个数recv_end_flag = 1;          //将接收标志位置为1HAL_UART_Receive_DMA(&huart1, ReceiveBuff, BUFFERSIZE);//重新开启DMA,因为之间为了读数据关闭过一次}}

(4)我们再次回到“main.c“文件中,来处理我们的这些数据,

我们直接将代码输入进去即可完成,应该都可以看的动,就是将得到的数据提取出来,然后标志位和数据长度清零就可以了。

usart1_printf("%c%c%c%c%c%c%c%c", 0x02,0x03,0x00,0x00,0x00,0x01,0x84,0x39);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
if(recv_end_flag == 1){wind_speed = (ReceiveBuff[3]*256 + ReceiveBuff[4])/10.0;usart2_printf("wind_speed:%.3f\r\n", wind_speed);Rx_len=0;recv_end_flag=0;
}
HAL_Delay(500);

(5)我们点击编译,之后使用STLINK烧录到我们的单片机中即可。


总结

这次是我第一次调试485设备,在自己调试之前也是拖了很久,因为之前没接触过感觉很难,一直不愿意上手,但是做还是要做了,最终经过自己查资料和调试之后也做出来了,所以说有的时候,我们要有迈出第一的勇气,只有开始做才能真正地体会到吸取知识的快乐。通过本次实验我学会了:
(1)如何对多个串口进行重定向,提高了开发效率;
(2)在调试带有485或者串口之类通信协议的设备之前,可以先用“”串口调试助手“”这类的工具先看看设备有没有问题;
(3)掌握了串口设备的发送与接收整个的流程,这样可以形成自己一个模板,后期提高自己的开发效率。

记录今天在朋友圈看到的一句话:
我从来不曾优秀过,但也从来不曾放弃过!

毕业设计1-DFROBOT 风速计 调试记录(基于485协议+ STM32Cubemx + STM32F103C8T6)相关推荐

  1. python操作hbase配置记录-基于thrift2协议

    #--------------------------------------下面是基本知识------------------------------------------------------ ...

  2. JAVA基于的智慧小区计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA基于的智慧小区计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA基于的智慧小区计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语言: ...

  3. 基于FPGA的FOC电流采样Bug调试记录

    #基于FPGA的FOC电流采样Bug调试记录 博主在调试FOC闭环控制中遇到了一个bug,冥思苦想两三天,最终一步步地调试时序,最终找到了bug,在调试过程中学会了debug的思想,也明白了调试过程中 ...

  4. TI DSP28377D芯片上基于UDS的BOOT调试记录

    本次开发所用平台为TI的DSP芯片,型号TMS320F28377D.在开发过程中难点是芯片的驱动调试,下面记录在开发中的调试记录及问题点和解决方式. 首先本芯片在官方能够得到例程,但是未找到例程的完善 ...

  5. JAVA儿童接种系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA儿童接种系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA儿童接种系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语言:Ja ...

  6. JAVA宠物医院管理系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA宠物医院管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA宠物医院管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语 ...

  7. JAVA菜鸟驿站快递分发系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA菜鸟驿站快递分发系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA菜鸟驿站快递分发系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 ...

  8. WK2204 - spi转uart调试记录

    WK2204 - spi转uart调试记录 硬件 芯片简介 电路设计 驱动 添加设备树 添加驱动 调试 查看启动加载 检查串口通信 数据乱码或丢失 RS485只能收不能发 系统中断响应异常 思考 硬件 ...

  9. JAVA诊所信息管理系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA诊所信息管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA诊所信息管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语 ...

最新文章

  1. 互联网协议 — Non-IP 网络架构
  2. 判断TImage图片的类型
  3. linux里根目录下的/bin,usr里的/usr/bin还有local里的/usr/local/bin有什么区别?
  4. java8新特性之lambda表达式(及方法引用与构造器引用)
  5. pytorch Dataset, DataLoader产生自定义的训练数据
  6. 二叉树学习——简单入门题
  7. mysql8.0导入备份_mysql8.0.20配合binlog2sql的配置和简单备份恢复的步骤详解
  8. kindEditor文本编辑器
  9. html 加粗_一篇文章带你了解HTML格式化元素
  10. RFC 5627 SIP中文翻译
  11. 507.Wiggle Sort II-摆动排序 II(中等题)
  12. java seek_java中seek()的用法,seek和seekfor有什么区别
  13. php网络编程socket通讯
  14. 火狐怎么导入旧的火狐数据_如何与Firefox分手
  15. [附源码]java毕业设计领导干部听课评课管理系统
  16. Python+OpenCV 识别银行卡卡号
  17. Android离线文字转语音(TTS)原生实现
  18. 基于Java的Minecraft游戏后端自定义插件 04注册命令与处理
  19. 明日又天涯——蝶舞萧霞
  20. Nginx配置信息损毁又无备份时如何恢复

热门文章

  1. 51单片机基础入门(2)点灯大师:单个LED点亮、多个LED点亮、流水灯(附程序代码、解析)
  2. 定积分的计算(换元法)习题
  3. OSPF常用环境配置实战
  4. 中华云盒M1刷Linux教程,再谈中华云盒M1刷机详细教程,包教包会终结版
  5. Logback设置日志级别
  6. ​Python 3.7.0 程序下载 32/64位含安装教程|支持Win10
  7. php的redis单例模式
  8. 键盘组合键映射_如何在键盘上重新映射Office键
  9. JQ动画和特效轮播图
  10. Euraka-看这就够了