基于STM32F4的多摩川协议通讯

这篇具有很好参考价值的文章主要介绍了基于STM32F4的多摩川协议通讯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、介绍

       之前项目刚好有用到禹衡家的17位绝对值编码器,趁着周末有时间整理一下开发思路,同时也分享出来给有需要的人做做参考。

       说回编码器,我们都知道在伺服控制中,为了获取更高的位置精度,完成更精细的绝对定位,通常会采用绝对式光电编码器作为位置反馈传感器,其常见的两种主要是17位与23位,编码器厂商为了增强信息传输可靠性,编码信息一般会采用串行方式输出,通过特定的通讯协议控制。这里我们主要介绍一下17位绝对式光电编码器。

2、编码器

2.1、接口定义

基于STM32F4的多摩川协议通讯

说明:实际应用过程中,如果没有多圈值记录需求,可以不接电池,但如果需要长时间保留多圈值数据,比如多轴机器人的原点数据,这种情况则需要接入电池。

2.2、电气参数

基于STM32F4的多摩川协议通讯

说明:1、输出信号符合RS485接口,负载电流Imax:±50mA;

  2、消耗电流:≤120mA(无负载情况);

  3、绝缘阻抗10MΩ以上(0V与壳之间,DC500V);

2.2、通讯电路

基于STM32F4的多摩川协议通讯

说明:1、IC1为线性差分驱动器,功能等同于MAX485;

             2、IC2为线性差分接收器,功能等同于MAX485,推荐使用ADM485;

  3、匹配电阻:编码器匹配电阻R2为220Ω,推荐用户接收端匹配电阻R5120Ω

  4、上/下拉电阻:编码器上/下拉电阻R1、R3为4.7KΩ,推荐用户接收端上/下拉电阻R4R6不小于1KΩ

2.3、协议

根据编码器电气参数与通讯电路,我们可以确定通讯方式,STM32采用USART模块,串口波特率设置2.5Mbps,以下是多摩川协议时序图:

说明:1、CF:控制域,用户发送命令CF与编码器返回的CF一致;

  2、SF:状态域,编码器返回错误信息与报警信息;

  3、DF:数据域,编码器返回数据;

  4、CRC:校验域,CRC多项式:G(X)=𝑋8+1校验范围CFSFDF基于STM32F4的多摩川协议通讯

2.3.1、控制字CF

基于STM32F4的多摩川协议通讯

说明:1、根据时序图可以知道发送请求只需要发送CF即可,具体CF值可以根据上表分析,CF结构主要是start bit(0)+sink code+Data ID code+ID parity+Delimiter(1),这里注意一下开始位(0)与结束位(1),与串口无校验发送里面的开始位与结束位一样的嘛,所以我们其实只需要发送sink code+Data ID code+ID parity就可以了;

  2、根据时序图可以看到sink code 固定为010,剩下的Data ID code+ID parity看自己需求查表对应上就行,经常用的主要是ID0=0x02与ID3=0x1A,其余我就不说了,贴代码。

  3、这里注意一下,编码器返回的报文CF位必须与发送CF一致,在处理接收报文时需校验一下。

/* 宏定义声明 ----------------------------------------------------------------*/

#define         DataId0             0x02                                        /*读取单圈*/

#define         DataId1             0x8A                                        /*读取圈数*/

#define         DataId2             0x92                                        /*读取编码器编号*/

#define         DataId3             0x1A                                        /*读取单圈+圈数*/

#define         DataId6             0x32                                        /*EEPROM*/

#define         DataIdD             0xEA                                        /*EEPEOM*/

#define         DataId7             0xBA                                        /*重置错误ERROR*/

#define         DataId8             0xC2                                        /*重置圈数*/

#define         DataIdC             0x62                                        /*重置圈数与ERROR*/  

2.3.2、状态字SF

基于STM32F4的多摩川协议通讯

说明:状态位SF主要反馈编码器状态,包括编码器是否过热、电池供电是否正常、数据解析是否正确等。

2.3.3、数据字DF

根据发出的CF不同,编码器返回的DF也会不同,具体的对应关系如下表:

基于STM32F4的多摩川协议通讯

说明:1、ABS0-ABS2:编码器单圈值,由于STM32的串口是小端模式,所以实际 编码器单圈位置值=(ABS2<<16)|(ABS1<<8)|(ABS0<<0);

  2、ABM0-ABM2:编码器圈数值,实际编码器圈数值=(ABM2<<16)|(ABM1<<8)|(ABM0<<0)。

基于STM32F4的多摩川协议通讯

说明:ALMC:编码器错误,不同数值都有其对应的故障,对应查表即可。

2.4.4、校验字CRC

基于STM32F4的多摩川协议通讯

说明:这里注意一下,我们采用的是小端异或的计算方式,根据多项式 G(X)=𝑋8+1 其对应的二进制数为0x101,其Ploy值为0x01,LSB First=0x80,我们需要将CF+SF+DF以字节形式分别于LSB First进行亦或处理,最后结果为CRC8校验结果,具体实现过程见代码。基于STM32F4的多摩川协议通讯

/******************************************************************************

  * 函数功能:   CRC8校验函数

  * 输入参数:   *message:接收的数据指针

                len:数据长度

  * 返 回 值:      CRC8校验值

    * 说    明: 多项式:G(X)=X^8+1 LSB first  Poly: 0000 0001

                        LSB first  : 1000 0000 =0X80

*****************************************************************************/  

uint8_t APP_Math_CRC8_ChkValue(uint8_t *message, uint8_t len)

{

    uint8_t crc_val;

    uint8_t i;

    crc_val = 0;

    while(len--)

    {

        crc_val ^= *message++;

        for(i = 0;i < 8;i++)

        {

            if(crc_val & 0x01)

                crc_val = (crc_val >> 1) ^ 0X80;

            else

                crc_val >>= 1;

        }

    }

    return crc_val;

}

3、单片机

3.1、单片机

当时项目为了上手快一点,又怕串口波特率不够,所以就选了个STM32F405RGT6,168MHz主频绰绰有余,现在想想有点杀鸡用牛刀了,这里主要提一下接下来要用到的串口与DMA。STM32F405有16数据流DMA,支持FIFOs模式与触发模式,4 个 USART/2 个 UART(速率可达10.5 Mbit/s,支持ISO7816接口)。

基于STM32F4的多摩川协议通讯

3.2、串口+DMA

 串口(UART)是一种低速的串行异步通信,通常使用的波特率小于或等于115200bps,对于这种数据量不大的通信场景,一般没必要使用DMA,或者说使用DMA并未能充分发挥出DMA的作用。当面对数量大或者高波特率时,就必须使用DMA以释放CPU资源,因为高波特率可能带来CPU资源过度浪费的问题。这里编码器电气参数要求通讯速率≥2.5MHz,我们一般选择将串口波特率设置为2.5MHz,同时为了不占用太多CPU资源,CF发送与编码器数据接收都会采用DMA,具体寄存器设置如下:

/******************************************************************************

  * 函数功能:   USART2+DMA初始化函数

  * 输入参数:   无

  * 返 回 值:      无

    * 说    明:   外部调用-多摩川编码器1

*****************************************************************************/  

void BSP_Encoder1_InitConfig(void)

{

    GPIO_InitTypeDef    GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

    DMA_InitTypeDef     DMA_InitStructure;

    NVIC_InitTypeDef    NVIC_InitStructure;

   

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);                                         /*UART2-TX*/

    GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);                                         /*UART2-RX*/

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                                                       /*UART2-TX*/

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

    GPIO_Init(GPIOA, &GPIO_InitStructure);                                                          /*UART2-RX*/

   

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);  

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;                                                    /*DIR1-PC15*/

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;  

    GPIO_Init(GPIOC,    &GPIO_InitStructure);  

    GPIO_ResetBits(GPIOC,GPIO_Pin_15);                                                              /*初始化关闭通信*/

   

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);                                             /*串口发DMA配置*/

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                                                 /*抢占优先级0-3,响应优先级0-3*/

    NVIC_InitStructure.NVIC_IRQChannel=DMA1_Stream6_IRQn;              

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;                                         /*抢占优先级1*/

    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;

    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

    NVIC_Init(&NVIC_InitStructure);                                                                 /*DMA发送中断*/

    DMA_DeInit(DMA1_Stream6);                                                                       /*DMA通道配置*/

    while(DMA_GetCmdStatus(DMA1_Stream6)!=DISABLE){}    

    DMA_InitStructure.DMA_Channel = DMA_Channel_4;

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);                             /*外设地址*/

    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Ed_Tx_Buf1;                                   /*内存地址*/

    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                                         /*dma传输方向*/

    DMA_InitStructure.DMA_BufferSize = USART_MAX_TX_LEN;                                            /*设置DMA在传输时缓冲区的长度*/

    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                                /*设置DMA的外设递增模式,一个外设*/

    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                         /*设置DMA的内存递增模式*/

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;                         /*外设数据字长*/

    DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;                             /*内存数据字长*/

    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                   /*设置DMA的传输模式*/

    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                             /*设置DMA的优先级别*/

    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                                          /*指定如果FIFO模式或直接模式将用于指定的流:不使能FIFO模式*/  

    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;                               /*指定了FIFO阈值水平*/  

    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                                     /*指定的Burst转移配置内存传输*/

    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;                             /*指定的Burst转移配置外围转移*/

    DMA_Init(DMA1_Stream6, &DMA_InitStructure);                                                     /*配置DMA1的通道*/    

    DMA_ITConfig(DMA1_Stream6,DMA_IT_TC,ENABLE);                                                    /*使能中断*/

   

    DMA_DeInit(DMA1_Stream5);                                                                       /*串口接收DMA配置*/

    while(DMA_GetCmdStatus(DMA1_Stream5)!=DISABLE){}        

    DMA_InitStructure.DMA_Channel = DMA_Channel_4;

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);                             /*外设地址*/

    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Ed_Rx_Buf1;                                   /*内存地址*/

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                                         /*DMA传输方向*/

    DMA_InitStructure.DMA_BufferSize = USART_MAX_RX_LEN;                                            /*设置DMA在传输时缓冲区的长度*/

    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                                /*设置DMA的外设递增模式,一个外设*/

    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                         /*设置DMA的内存递增模式*/

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;                         /*外设数据字长*/

    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                                 /*内存数据字长*/

    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                   /*设置DMA的传输模式*/

    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                                         /*设置DMA的优先级别*/

    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                                          /*指定如果FIFO模式或直接模式将用于指定的流 : 不使能FIFO模式*/    

    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;                               /*指定了FIFO阈值水平*/    

    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                                     /*指定的Burst转移配置内存传输*/      

    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;                             /*指定的Burst转移配置外围转移*/

    DMA_Init(DMA1_Stream5, &DMA_InitStructure);                                                     /*配置DMA1的通道*/  

    DMA_Cmd(DMA1_Stream5,ENABLE);                                                                   /*使能通道*/

    USART_InitStructure.USART_BaudRate = ENCODER1_BAUDRATE;                                         /*配置8 1 0*/

    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    USART_InitStructure.USART_StopBits = USART_StopBits_1;

    USART_InitStructure.USART_Parity = USART_Parity_No ;

    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART2, &USART_InitStructure);

   

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;                                               /*通道设置为串口中断*/  

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;                                       /*中断占先等级*/

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                                              /*中断响应优先级*/

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                 /*打开中断*/  

    NVIC_Init(&NVIC_InitStructure);                                                                 /*配置中断*/  

   

    USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);                                                    /*采用DMA方式发送*/

    USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);                                                    /*采用DMA方式接收*/

    USART_ITConfig(USART2,USART_IT_TC,DISABLE);                                                     /*中断配置*/

    USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);

    USART_ITConfig(USART2,USART_IT_TXE,DISABLE);

    USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);                                                    /*开启USART2空中断*/

    USART_Cmd(USART2, ENABLE);                                                                      /*启动串口*/  

}

另附DMA1、DMA2每个控制的8个数据流和其对应的通道:

基于STM32F4的多摩川协议通讯 

基于STM32F4的多摩川协议通讯

4、代码实现

至此串口DMA初始化完成,接下来就是具体的发送与接收,发送直接采用DMA传输完成中断,接收稍微需要点处理,因为我们接收的是不定长度的数据,所以需要通过串口的空闲中断来判断数据接收结束,数据接收完毕之后需要对CF、CRC进行校验,校验通过才可认为DF数据可用,具体代码实现如下:

/******************************************************************************

  * 函数功能:       USART2中断处理函数

  * 输入参数:   无

  * 返 回 值:      无

    * 说    明:   外部调用-多摩川编码器1

*****************************************************************************/  

void USART2_IRQHandler(void)                                                                        /*串口2中断服务程序*/

{

    if(USART_GetITStatus(USART2,USART_IT_IDLE)!=RESET)                                              /*空闲中断触发*/

    {

        DMA_Cmd(DMA1_Stream5, DISABLE);                                                             /* 暂时关闭DMA数据尚未处理 */

        ED_RX_LEN1 = USART_MAX_RX_LEN - DMA_GetCurrDataCounter(DMA1_Stream5);                       /* 获取接收到的数据长度*/

        BSP_Encoder1_DMA_DataProcess(Ed_Tx_Buf1,Ed_Rx_Buf1,ED_RX_LEN1);                             /* 报文数据处理*/

        DMA_ClearFlag(DMA1_Stream5,DMA_FLAG_TCIF5);                                                 /* DMA标志位 */

        DMA_SetCurrDataCounter(DMA1_Stream5,USART_MAX_RX_LEN);                                      /* 重新赋值计数值,必须大于等于最大可能接收到的数据帧数目 */

        DMA_Cmd(DMA1_Stream5, ENABLE);                                                              /*打开DMA*/

        USART_ReceiveData(USART2);                                                                  /*清除空闲中断标志位,接收函数有清标志位的作用*/

        Ed_Flag_Rx_Busy1 = 1;                                                                       /*状态位更新-USART2接收完成*/            

    }

    if(USART_GetFlagStatus(USART2,USART_IT_TXE)==RESET)                                             /*串口发送完成*/

    {

        Ed_Flag_Tx_Busy1=0;                                                                                                                    

        USART_ITConfig(USART2,USART_IT_TC,DISABLE);

    }

}

/******************************************************************************

    * 函数功能:     DMA1_Stream6中断处理函数

    * 输入参数:     无

    * 返 回 值:    无

    * 说    明:   外部调用-多摩川编码器1

*****************************************************************************/  

void DMA1_Stream6_IRQHandler(void)

{

    if(DMA_GetFlagStatus(DMA1_Stream6,DMA_FLAG_TCIF6)!=RESET)                                       /*等待DMA1_Steam6传输完成*/

    {

        DMA_ClearFlag(DMA1_Stream6,DMA_FLAG_TCIF6);                                                 /*清除DMA1_Steam6传输完成标志*/

        DMA_Cmd(DMA1_Stream6,DISABLE);                                                                          /*关闭使能*/

        USART_ITConfig(USART2,USART_IT_TC,ENABLE);                                                  /*打开串口发送完成中断*/

    }

}

/******************************************************************************

    * 函数功能:     DMA_USART2发送函数

    * 输入参数:     *data:发送的数据指针

                    size:数据长度

    * 返 回 值:    无

    * 说    明:   外部调用-多摩川编码器1

*****************************************************************************/  

void BSP_Encoder1_DMA_SendBuffer(u8 *data,u16 size)                                                            

{

    Ed_Flag_Tx_Busy1=1;                                                                             /*状态位更新-USART2发送中*/

    memcpy(Ed_Tx_Buf1,data,size);                                                                   /*复制数据到DMA发送缓存区*/

    while (DMA_GetCmdStatus(DMA1_Stream6) != DISABLE);                                              /*确保DMA可以被设置*/

    DMA_SetCurrDataCounter(DMA1_Stream6,size);                                                      /*设置数据传输长度*/

    DMA_Cmd(DMA1_Stream6,ENABLE);                                                                   /*打开DMA数据流,开始发送*/

}

/******************************************************************************

    * 函数功能:     DMA_USART2数据处理函数

    * 输入参数:     *data:接收的数据指针

                    size:数据长度

    * 返 回 值:    无

    * 说    明:   外部调用-多摩川编码器2

*****************************************************************************/  

void    BSP_Encoder1_DMA_DataProcess(u8 *txdata,u8 *rxdata,u16 size)

{

    uint8_t     crc=0;

    uint8_t     buf[USART_MAX_RX_LEN]={0};  

    for(int i=0;i<size;i++)

        buf[i]=*rxdata++;

    if(buf[0]==*txdata)

    {

        crc=APP_Math_CRC8_ChkValue(buf,size-1);

        if(crc==buf[size-1])

        {

            Encoder1_CodeValue=buf[4]<<16|buf[3]<<8|buf[2];

        }

        else

        {

            Encoder_ReadFaultNum++;

            if(Encoder_ReadFaultNum>ED_READ_FAULT_MAXNUM)

                Encoder_ReadStatus=1;          

        }

    }

    else

    {

            Encoder_ReadFaultNum++;

            if(Encoder_ReadFaultNum>ED_READ_FAULT_MAXNUM)

                Encoder_ReadStatus=1;

    }

}

5、结语

整个项目其实难度并不大,对我个人而言花费时间多的主要还是在搞懂DMA、CRC校验原理、发送\接收中断处理这上面。本人对单片机也还是小白阶段,很多东西都是重头开始吸收学习,不过万变不离其宗,多花点时间搞清楚原理,很多不解的地方都会豁然开朗。技术分享就到这里了,希望能对你有所帮助!!文章来源地址https://www.toymoban.com/news/detail-515256.html

到了这里,关于基于STM32F4的多摩川协议通讯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【stm32开发笔记】基于HAL库的STM32F4添加DSP库

    本文分两种方法添加DSP库:1.CubeMX直接配置ioc添加; 2.KEIL内添加; 简述:补齐全部lib库-添加DSP包-使能DSP勾选-添加头文件及魔术棒配置-测试 1.补齐lib库。( 如果使用直接默认添加的库,是不支持FPU的,所以需要补齐后找到所需的lib文件进行替换,在MX的工程管理栏,选择复制所

    2024年02月16日
    浏览(58)
  • 基于STM32F4的CANOpen移植教程(超级详细)

    本专题相关教程: 基于STM32F4的CANOpen移植教程 基于STM32F4的CANopen快速SDO通信 linux下CANopen for python的使用 基于Linux C的CANopen移植 CANopen补充–时间计算出错 CANopen补充–主站检测节点是否在线 为了在STM32F4上能够运行CANopen(CanFestival),跟着网上的教程操作,发现总是不够详细。

    2024年02月02日
    浏览(46)
  • 关于LWIP用法之HTTPD:基于STM32F4搭建web服务器

    一,STM32CUBEMX配置(使用的是6.4.0版本) 前提是在配置好LWIP的情况下(能ping通你的开发板),使能HTTPD功能。 然后是使能LWIP_HTTPD_CGI, 使能:LWIP_HTTPD_SUPPORT_POST(), 使能 :HTTPD_USE_CUSTOM_FSDATA。 会发现fs.c这个文件的#include HTTPD_FSDATA_FILE,这一句编译报错,解决办法:1) 在KEIL中lwipop

    2023年04月08日
    浏览(38)
  • 运动控制器设计——基于FreeModbus在STM32F4平台实现ModbusTCP和ModbusRTU

    本文笔者最近的项目是设计一款运动控制器,MCU使用的是STM32F429,要求是通过Modbus TCP协议实现与示教器通讯,并通过ModbusRTU实现与触摸屏通讯。 本文将介绍在STM32F4上实现 ModbusTCP和ModbusRTU通讯 的过程。笔者才疏学浅,如有错误还请指正。 Modbus协议是典型的主-从通讯结构,链

    2024年02月05日
    浏览(55)
  • GD32F4移植STM32F4

    近期在项目中采用了GD32F407VET6替换原项目中的STM32F407VET6,网传GD的兼容性很好,之前也用F1系统的替换了一下,按照CSND各位大佬的经验一步步改进了代码,测试直接通过,现在也一直在项目中实际应用了,一直没有出问题。 所以这SMT时,嘉立创没有STM的货果断换成了GD,可换时

    2024年02月16日
    浏览(83)
  • 基于STM32F1以及STM32CubeMx实现串口中断通讯(字符串发送与接收)

    首先选好自己的板子并打开软件设置,本实验基于STM32F103ZET6实现,打开软件后如图: 打开外部高速晶振,然后接着配置时钟: 将时钟频率修改为72MHz,接着设置接线方式为SW 接下来需要使用串口中断通讯,打开我们的串口设置并打开中断 这里波特率设置为115200,数据位为

    2024年02月09日
    浏览(47)
  • 基于STM32F4的FFT+测频率幅值相位差,波形显示,示波器,时域频域分析相关工程

    一入电赛深似海,此话不假,个人感觉很累,但是收获确实多。本人去年参加了国赛,电赛提前半个月就开始着手准备了,只记得那时候不是调试就是在调试的路上,也因此留下了宝贵的我姑且称之为“经验”,作为一名小白,借此机会跟各位老白和小白分享一下。我训练较

    2024年02月03日
    浏览(52)
  • STM32F3系列 SPI通讯缺帧问题(基于LL库)

    芯片型号:STM32f303RBT6 开发软件:MDK5 CubeMX VS Code 主机使用SPI-DMA中断发送数据,从机接收数据总是少3个数据(16bit)。 主机SPI发送完成后,片选线拉高太快,导致从机片选消失,故最后几个数据没有接收到; 错误图片 : 在SPI发送数据后,延迟一段时间,拉高片选(CS)线。 程

    2024年02月04日
    浏览(44)
  • 【STM32】STM32F4 GPIO详解与配置

    GPIO是通用输入输出端口的简称,为STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。STM32芯片的GPIO被分成很多组,每组有16个引脚,所有的GPIO引脚都有基本的输入输出功能。 其中保护二极管使GPIO能够5V电压容忍。在

    2024年02月07日
    浏览(52)
  • STM32F4Timer

    ref https://blog.csdn.net/zhuxinmingde/article/details/131784852?ops_request_misc=request_id=biz_id=102utm_term=STM32%20%E9%AB%98%E7%BA%A7%EF%BC%8C%E6%99%AE%E9%80%9A%EF%BC%8C%E5%9F%BA%E6%9C%AC%E5%AE%9A%E6%97%B6%E5%99%A8utm_medium=distribute.pc_search_result.none-task-blog-2 all sobaiduweb~default-1-131784852.142 v99 controlspm=1018.2226.3001.4187 1. Timer re

    2024年02月02日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包