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

 

posted @ 2022-10-20 21:29  jamaal555  阅读(839)  评论(0)    收藏  举报