stm32移植vofa
一、配置目的
这里只是想作为虚拟示波器来使用,32只发送数据,波特率越高越好,max488极限速度为5Gbps。
二、关键点
1、vofa协议帧
2、串口如何发送float数据
3、32的DMA使用方法
三、vofa协议帧

帧尾是一个固定的32bit数。float在32中也是32bit的。如果我一次想发送3个float 数据:pmsm.currA,pmsm.currB,pmsm.currC (实际上vofa要求一次三个channel是同时发送的),那我一帧的结构就是 float float float end (32bit 32bit 32bit 32bit 共128bit)。按照我的开关频率40kHz来计算,一次中断发送一次数据,那么40k*128bit=5120000bit/s = 5000kbit/s = 4.88Mbit/s = 4.88Mbps,远小于5Gbps。
这个线和abz是同层的,可能会有干扰,不行就得降速了。最低速度:1000Hz频率,最起码10倍,即串口的发送速率为10kHz,10k*128bit=1280000bit/s=1.22Mbps.
四、串口发送float数据的方法
1、float转u8
正点原子的历程都是u8 u16的收发等等,那么第一种常见的发送float的方法就是将float小数*10000扩大一万倍,再强制类型转换为int,再发送。但是这种方法会丧失精度(0.0001),而且强制位转浪费时间。
可以看下边这篇文章:
https://www.ngui.cc/51cto/show-605348.html?action=onClick
2、memcpy()方法
把float复制到一块u8定义的内存中,后边发送这块内存中的数据。
float tempFloat[3]; //要发送的3个float源数据 uint8_t tempData[16]; //定义的传输Buffer(串口真正发送的数据) memcpy(tempData, (uint8_t *)tempFloat, sizeof(tempFloat));//通过拷贝把数据重新整理,把float复制到u8中 tempData[12] = 0x00; //写如结尾数据 tempData[13] = 0x00; tempData[14] = 0x80; tempData[15] = 0x7f; HAL_UART_Transmit_IT(&huart6, (uint8_t *)tempData, 16); //通过串口传输16个数据
https://blog.csdn.net/weixin_42316458/article/details/114254766?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166616421616782428633099%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166616421616782428633099&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-114254766-null-null.142^v59^pc_search_tree,201^v3^add_ask&utm_term=vofa%E6%98%BE%E7%A4%BA%E6%B3%A2%E5%BD%A2stm32&spm=1018.2226.3001.4187
https://blog.csdn.net/weixin_42665184/article/details/125807711?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166616421616782428633099%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166616421616782428633099&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-125807711-null-null.142^v59^pc_search_tree,201^v3^add_ask&utm_term=vofa%E6%98%BE%E7%A4%BA%E6%B3%A2%E5%BD%A2stm32&spm=1018.2226.3001.4187
3、结构体/联合体方法
(1)联合体方法:定义一个联合体u{float a, u8 b[4]},这样总长度就是最大的成员的长度(a b都是4),把要发送的float数据传到u.a中,在串口中发送u.b,在接收端接收u2.b,使用u2.a。如果是发送3个float,定义u{float a[3], u8 b[12]}即可。
发送完数据后,再发送尾帧。
https://blog.csdn.net/qq_44675660/article/details/122331908 https://blog.csdn.net/PaxiuA/article/details/120543642?ops_request_misc=&request_id=&biz_id=102&utm_term=vofa%E6%98%BE%E7%A4%BA%E6%B3%A2%E5%BD%A2stm32&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-120543642.nonecase&spm=1018.2226.3001.4187
(2)结构体方法:实际上结构体也可以,就按照官方定义:
#define CH_COUNT (3) typedef struct Frame { //32位机中,一个float占用32bit(4Byte) float fdata[CH_COUNT]; //vofa发送一次数据, 必须加入一个32bit的针尾 unsigned char tail[4]; //{0x00, 0x00, 0x80, 0x7f}; //这个结构体包括fdata——3个float和一个帧尾(32bit) } Frame_t;
发送时,按u8发送,长度sizeof(Frame_t)即可。无需其他处理了。
(3)补充
结构体是按照单元存放的(因为要对齐),单元长度等于最长的成员长度,这里各个成员都是32bit,所以单元长度是32bit,总长度是128bit。
https://blog.csdn.net/qq_26106893/article/details/123260167 https://blog.csdn.net/weixin_39876856/article/details/117020583
串口发送结构体:
https://blog.csdn.net/qq_33904382/article/details/112718948
五、串口DMA使用方法

一般不用硬件流控制。(Tx Rx gnd即可)
这里设两万是ch340的及限速率。

这里dma发送到底是否需要打开串口?————待测试 https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=608538&highlight=dma https://blog.csdn.net/u012780337/article/details/100640423
明面上是需要的,因为进入到HAL_UART_Transmit_DMA这个函数中可以看到,它将DMA传输完成、半完成、错误的回调函数分别定向到了串口DMA传输完成、半完成、错误的回调
函数UART_DMATransmitCplt、UART_DMATxHalfCplt、UART_DMAError。但在GD中没有打开中断也没有任何问题。
下边这篇文章提到了,对F1必须打开串口中断,并且还必须写回调函数,但是F7中不需要。?
https://blog.csdn.net/qq_30267617/article/details/118877845 ****
(经测试,在F4中,必须打开中断。但是不用谢中断回调函数。)

fifo是用来匹配源端和终端的字长的(拆包)。burst是保证一个节内数据传送不被打断的。
加入vofa.h:
#ifndef _VOFA_H_ #define _VOFA_H_ #define CH_COUNT (3) typedef struct Frame { float fdata[CH_COUNT]; //vofa发送一次数据, 必须加入一个32bit的针尾 unsigned char tail[4]; //{0x00, 0x00, 0x80, 0x7f}; //这个结构体包括fdata——3个float和一个帧尾(32bit) } Frame_t; static inline void FRAME_Init(Frame_t *f) //加入vofa的32位针尾, 固定为00 00 80 7f,在main中初始化一次 { f->tail[0] = 0x00; f->tail[1] = 0x00; f->tail[2] = 0x80; f->tail[3] = 0x7f; } extern Frame_t board_upload_buff; //串口发波缓冲结构体 #define BOARD_UPLOAD_REMAIN_SIZE (__HAL_DMA_GET_COUNTER(&hdma_usart1_tx)) //切换前,判断是否本次dma发送完毕。 void cntl_upload(void); //通道切换函数 void BOARD_UploadStart(void); //DMA发送函数 #endif
加入vofa.c:
#include "vofa.h" #include "main.h" #include "cntl_algorithm.h" uint8_t cntl_upload_switch = 0; extern MOTOR pmsm; extern DMA_HandleTypeDef hdma_usart1_tx; extern UART_HandleTypeDef huart1; void cntl_upload(void) //这个是切换显示通道的函数 { if (BOARD_UPLOAD_REMAIN_SIZE == 0) { //DMA剩余要发送的数据为0, 才可以切换 switch (cntl_upload_switch) { default: case 0: board_upload_buff.fdata[0] = pmsm.currA; board_upload_buff.fdata[1] = 0; board_upload_buff.fdata[2] = pmsm.theta; break; case 1: board_upload_buff.fdata[0] = 0; board_upload_buff.fdata[1] = 0; board_upload_buff.fdata[2] = 0; break; } BOARD_UploadStart(); //没发完,本次中断不发送 } } Frame_t board_upload_buff; void BOARD_UploadStart(void) { __HAL_DMA_DISABLE(&hdma_usart1_tx); HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&board_upload_buff, sizeof(Frame_t)); //发送结构体(不用对float做处理了) __HAL_DMA_ENABLE(&hdma_usart1_tx); }
main.c加入:
FRAME_Init(&board_upload_buff); //在初始化时挂上帧尾 cntl_upload(); //dma发送,调用一次发送一次。一周期调用一次发送3个float,大概时间在2us-3us之间。同时波特率1.22bps<2bps,一个周期能够发送完毕。

附:vofa使用、介绍:
https://blog.csdn.net/PaxiuA/article/details/120543642?ops_request_misc=&request_id=&biz_id=102&utm_term=vofa%E6%98%BE%E7%A4%BA%E6%B3%A2%E5%BD%A2stm32&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-120543642.nonecase&spm=1018.2226.3001.4187 https://blog.csdn.net/weixin_42665184/article/details/125807711?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166616421616782428633099%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166616421616782428633099&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-125807711-null-null.142^v59^pc_search_tree,201^v3^add_ask&utm_term=vofa%E6%98%BE%E7%A4%BA%E6%B3%A2%E5%BD%A2stm32&spm=1018.2226.3001.4187 https://blog.csdn.net/weixin_42316458/article/details/114254766?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166616421616782428633099%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166616421616782428633099&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-114254766-null-null.142^v59^pc_search_tree,201^v3^add_ask&utm_term=vofa%E6%98%BE%E7%A4%BA%E6%B3%A2%E5%BD%A2stm32&spm=1018.2226.3001.4187

浙公网安备 33010602011771号