freemodbus移植进STM32(包含HAL库和标准库两种方法)

这篇具有很好参考价值的文章主要介绍了freemodbus移植进STM32(包含HAL库和标准库两种方法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

freemodbus移植

基于freemodbus1.6
使用HAL库
软件:stm32cubemx stm32cubeide

后续会更新标准库的移植。以及rtos下的移植(尽量)

下载freemodbus1.6

这个获取方法网上到处都是,不细说了。

cubemx新建工程

新建工程只列出了与移植freemodbus相关的设置
这里我使用的是485通信,所以额外使能了一个引脚
freemodbus移植进STM32(包含HAL库和标准库两种方法)
使能一个定时器,这里我用的是tim2。并且开始定时器2中断
freemodbus移植进STM32(包含HAL库和标准库两种方法)
其他设置如下图,参数其实设什么无所谓,因为后面要改的,我们并不用系统的初始化函数。
freemodbus移植进STM32(包含HAL库和标准库两种方法)
然后使能一个串口,我这里用的串口1,参数其实设什么无所谓,因为后面要改的,
freemodbus移植进STM32(包含HAL库和标准库两种方法)
这里可以把串口1和定时器2的最前面的取消勾选,就不会生成他们的初始化函数,不勾也没有太大关系,因为我们的函数在他之后,会覆盖掉系统的设置。
freemodbus移植进STM32(包含HAL库和标准库两种方法)

另外在中断优先级设置中,将串口优先级设置高于定时器2,数字越小越高。
freemodbus移植进STM32(包含HAL库和标准库两种方法)
相关的中断处理函数也要生成。
freemodbus移植进STM32(包含HAL库和标准库两种方法)

然后就可以generate code!生成代码。

代码修改

首先我们在我们项目的根目录中新建一个freemodbus文件夹,文件夹中再建一个modbus文件夹,一个port文件夹。
freemodbus移植进STM32(包含HAL库和标准库两种方法)
把你最开始下载下来的freemodbus中modbus文件夹中的内容复制到你刚才的modbus文件夹中,
freemodbus移植进STM32(包含HAL库和标准库两种方法)
把你最开始下载下来的freemodbus中demo/bare路径下的内容全部复制到你刚才的port文件夹中
freemodbus移植进STM32(包含HAL库和标准库两种方法)

然后我们进入cubeide,右键项目->属性,配置头文件和源文件路径。
freemodbus移植进STM32(包含HAL库和标准库两种方法)
把如图六个头文件路径添加。
freemodbus移植进STM32(包含HAL库和标准库两种方法)
把如图最下面两个源文件路径添加。
freemodbus移植进STM32(包含HAL库和标准库两种方法)

先在port.h文件中补充这两个宏定义,这是HAL库的全局中断开启、关闭函数。
freemodbus移植进STM32(包含HAL库和标准库两种方法)

ok,然后我们修改portserail.c
这两个函数前面的static标志去掉。
freemodbus移植进STM32(包含HAL库和标准库两种方法)
vMBPortSerialEnable函数修改如下

void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{
    /* If xRXEnable enable serial receive interrupts. If xTxENable enable
     * transmitter empty interrupts.
     */
	if (xRxEnable)						//将串口收发中断和modbus联系起来,下面的串口改为自己使能的串口
				{
					__HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE);	//我用的是串口2,故为&huart2
					HAL_GPIO_WritePin(EN485_GPIO_Port, EN485_Pin, GPIO_PIN_RESET);//
				}
			else
				{
					__HAL_UART_DISABLE_IT(&huart2,UART_IT_RXNE);
					HAL_GPIO_WritePin(EN485_GPIO_Port, EN485_Pin, GPIO_PIN_SET);//
				}
	if (xTxEnable)
				{
				HAL_GPIO_WritePin(EN485_GPIO_Port, EN485_Pin, GPIO_PIN_SET);//
					__HAL_UART_ENABLE_IT(&huart2,UART_IT_TXE);
				}//
			else
				{
				HAL_GPIO_WritePin(EN485_GPIO_Port, EN485_Pin, GPIO_PIN_RESET);//
					__HAL_UART_DISABLE_IT(&huart2,UART_IT_TXE);
				}

}

串口初始化函数如下

BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{
			huart2.Instance = USART2;
		    huart2.Init.BaudRate = ulBaudRate;
		    huart2.Init.StopBits = UART_STOPBITS_1;
		    huart2.Init.Mode = UART_MODE_TX_RX;
		    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
		    huart2.Init.OverSampling = UART_OVERSAMPLING_16;

		    switch(eParity)
		    {
		    // 奇校验
		    case MB_PAR_ODD:
		        huart2.Init.Parity = UART_PARITY_ODD;
		        huart2.Init.WordLength = UART_WORDLENGTH_9B;            // 带奇偶校验数据位为9bits
		        break;

		    // 偶校验
		    case MB_PAR_EVEN:
		        huart2.Init.Parity = UART_PARITY_EVEN;
		        huart2.Init.WordLength = UART_WORDLENGTH_9B;            // 带奇偶校验数据位为9bits
		        break;

		    // 无校验
		    default:
		        huart2.Init.Parity = UART_PARITY_NONE;
		        huart2.Init.WordLength = UART_WORDLENGTH_8B;            // 无奇偶校验数据位为8bits
		        break;
		    }

		    return HAL_UART_Init(&huart2) == HAL_OK ? TRUE : FALSE;
}

收发字节函数如下

BOOL
xMBPortSerialPutByte( CHAR ucByte )
{
    /* Put a byte in the UARTs transmit buffer. This function is called
     * by the protocol stack if pxMBFrameCBTransmitterEmpty( ) has been
     * called. */
	HAL_GPIO_WritePin(EN485_GPIO_Port, EN485_Pin, GPIO_PIN_SET);//

	    if(HAL_UART_Transmit (&huart2 ,(uint8_t *)&ucByte,1,10) != HAL_OK )
	        return FALSE ;//HAL_UART_Transmit最后一位形参为最大发送时间,
	    				  //超出改时间退出发送,可能导致485发送失败,可稍微长一点。
	    else
	        return TRUE;
}

BOOL
xMBPortSerialGetByte( CHAR * pucByte )
{
    /* Return the byte in the UARTs receive buffer. This function is called
     * by the protocol stack after pxMBFrameCBByteReceived( ) has been called.
     */
	   HAL_GPIO_WritePin(EN485_GPIO_Port, EN485_Pin, GPIO_PIN_RESET);

	    if(HAL_UART_Receive (&huart2,(uint8_t *)pucByte,1,10) != HAL_OK )
	        return FALSE ;
	    else
	        return TRUE;
}

然后我们修改porttimer.c
首先依旧去掉这个函数前的static标志,方便之后调用,函数声明和函数实体前的static都要去掉
freemodbus移植进STM32(包含HAL库和标准库两种方法)

然后修改这几个函数:
定时器初始化函数

BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
			TIM_ClockConfigTypeDef sClockSourceConfig = {0};
		    TIM_MasterConfigTypeDef sMasterConfig = {0};

		    htim2.Instance = TIM2;
		    htim2.Init.Prescaler = 3599;								// 50us记一次数
		    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
		    htim2.Init.Period = usTim1Timerout50us-1;					// usTim1Timerout50us * 50即为定时器溢出时间
		    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
		    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
		    if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
		    {
		        return FALSE;
		    }
		    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
		    if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
		    {
		        return FALSE;
		    }
		    sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
		    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
		    if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
		    {
		        return FALSE;
		    }

		    return TRUE;
}

然后是定时器开启、关闭、中断服务函数

inline void
vMBPortTimersEnable(  )
{
    /* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
		__HAL_TIM_CLEAR_IT(&htim2,TIM_IT_UPDATE);//避免程序一上电就进入定时器中断
		__HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE);
		__HAL_TIM_SET_COUNTER(&htim2, 0);		// 清空计数器
	    __HAL_TIM_ENABLE(&htim2);				// 使能定时器

}

inline void
vMBPortTimersDisable(  )
{
    /* Disable any pending timers. */
    __HAL_TIM_DISABLE(&htim2);				// 禁能定时器
	__HAL_TIM_SET_COUNTER(&htim2,0);
	__HAL_TIM_DISABLE_IT(&htim2,TIM_IT_UPDATE);
	__HAL_TIM_CLEAR_IT(&htim2,TIM_IT_UPDATE);
}

/* Create an ISR which is called whenever the timer has expired. This function
 * must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that
 * the timer has expired.
 */
void prvvTIMERExpiredISR( void )
{
    ( void )pxMBPortCBTimerExpired(  );
}

最后还有两处修改,有的教程中并没有提到这两处修改,应该是与vMBPortSerialEnable中使用USART_IT_TC还是USART_IT_TXE中断标志有关,如果使用USART_IT_TC中断的话需要添加这两处修改,就我目前使用USART_IT_TXE中断标志的情况下,加上这两处修改也并无问题,待后续研究明白了再更新

//启动第一次发送,进入发送完成中断
           xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur );
           pucSndBufferCur++;  /* next byte in sendbuffer. */
           usSndBufferCount--;
   		//添加代码end
 //插入代码begin
                if(eStatus==MB_ENOERR)
                {
                	xMBRTUTransmitFSM();  //发送一帧数据中第一个字节出发发送完成中断
                }
                //插入代码end

freemodbus移植进STM32(包含HAL库和标准库两种方法)
freemodbus移植进STM32(包含HAL库和标准库两种方法)

在系统的中断处理.c中添加以下的函数声明,有些教程是自己写的中断处理,这里我们还是用系统自己的。

freemodbus移植进STM32(包含HAL库和标准库两种方法)

定时器中断处理函数:

void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */

	  HAL_NVIC_ClearPendingIRQ(TIM2_IRQn);

  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */

  /* USER CODE END TIM2_IRQn 1 */
}

串口中断函数:

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
	  if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_RXNE)!= RESET)
	  		{
	  			prvvUARTRxISR();//接收中断
	  		}

	  	if(__HAL_UART_GET_IT_SOURCE(&huart2, UART_IT_TXE)!= RESET)
	  		{
	  			prvvUARTTxReadyISR();//发送中断
	  		}

	    HAL_NVIC_ClearPendingIRQ(USART2_IRQn);
  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}

在文档末尾user code 代码段添加定时器中断回调函数:

/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* NOTE : This function Should not be modified, when the callback is needed,
            the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
   */
	if(htim->Instance == TIM2)
	{
		prvvTIMERExpiredISR( );
	}

}
/* USER CODE END 1 */



回到main函数

freemodbus移植进STM32(包含HAL库和标准库两种方法)
首先包含几个头文件
在Private define段添加如下:

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
//输入寄存器起始地址
#define REG_INPUT_START       0x0001
//输入寄存器数量
#define REG_INPUT_NREGS       8
//保持寄存器起始地址
#define REG_HOLDING_START     0x0001
//保持寄存器数量
#define REG_HOLDING_NREGS     8

//线圈起始地址
#define REG_COILS_START       0x0001
//线圈数量
#define REG_COILS_SIZE        16

//离散寄存器起始地址
#define REG_DISCRETE_START    0x0001
//离散寄存器数量
#define REG_DISCRETE_SIZE     16
/* USER CODE END PD */

Private variables段添加如下:

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
//输入寄存器内容
uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
//输入寄存器起始地址
uint16_t usRegInputStart = REG_INPUT_START;

//保持寄存器内容
uint32_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x147b,0x3f8e,0x147b,0x400e,0x1eb8,0x4055,0x147b,0x408e};
//保持寄存器起始地址
uint16_t usRegHoldingStart = REG_HOLDING_START;

//线圈状态
uint8_t ucRegCoilsBuf[REG_COILS_SIZE / 8] = {0x01,0x02};
//离散输入状态
uint8_t usRegDiscreteBuf[REG_DISCRETE_SIZE / 8] = {0x01,0x02};

uint8_t testfalg=0;

extern unsigned char NUM [];
/* USER CODE END PV */

Private function prototypes段添加如下:

/* USER CODE BEGIN PFP */
/**
 * @Brief : 读输入寄存器处理函数,功能码04
 * @param  pucRegBuffer    保存输入寄存器值的缓存
 * @param  usAddress       寄存器地址
 * @param  usNRegs         读取个数
 * @return?eMBErrorCode?
 */
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;

    if( ( usAddress >= REG_INPUT_START )\
        && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - usRegInputStart );
        while( usNRegs > 0 )
        {
            *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] >> 8 );
            *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] & 0xFF );
            iRegIndex++;
            usNRegs--;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }

    return eStatus;
}

/**
 * @Brief : 读保持寄存器处理函数,功能码03
 * @param  pucRegBuffer
 * @param  usAddress
 * @param  usNRegs
 * @param  eMode
 * @return?eMBErrorCode?
 */
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
	eMBErrorCode    eStatus = MB_ENOERR;
	int             iRegIndex;


	if((usAddress >= REG_HOLDING_START)&&\
		((usAddress+usNRegs) <= (REG_HOLDING_START + REG_HOLDING_NREGS)))
	{
		iRegIndex = (int)(usAddress - usRegHoldingStart);
		switch(eMode)
		{
			case MB_REG_READ://�??? MB_REG_READ = 0
        	while(usNRegs > 0)
				{
					*pucRegBuffer++ = (uint8_t)(usRegHoldingBuf[iRegIndex] >> 8);
					*pucRegBuffer++ = (uint8_t)(usRegHoldingBuf[iRegIndex] & 0xFF);
          			iRegIndex++;
          			usNRegs--;
				}
        	break;
			case MB_REG_WRITE://�??? MB_REG_WRITE = 1
			while(usNRegs > 0)
				{
					usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
          			usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
          			iRegIndex++;
          			usNRegs--;
        		}
		}
	}
	else//错误
	{
		eStatus = MB_ENOREG;
	}

	return eStatus;
}

/**
  *****************************************************************************
  * @Name   : 操作线圈
  *
  * @Brief  : 对应功能�???0x01 -> eMBFuncReadCoils
  *                    0x05 -> eMBFuncWriteCoil
  *                    0x15 -> 写多个线�??? eMBFuncWriteMultipleCoils
  *
  * @Input  : *pucRegBuffer:数据缓冲区,响应主机用
  *           usAddress:     寄存器地�???
  *           usNRegs:       操作寄存器个�???
  *           eMode:         功能�???
  *
  * @Output : none
  *
  * @Return : Modbus状�?�信�???
  *****************************************************************************
**/
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{
	eMBErrorCode	eStatus = MB_ENOERR;
	int 			iNCoils = ( int )usNCoils;
	unsigned short	usBitOffset;

	/* Check if we have registers mapped at this block. */
	if( ( usAddress >= REG_COILS_START ) &&	( usAddress + usNCoils <= REG_COILS_START + REG_COILS_SIZE ) )
	{
		usBitOffset = ( unsigned short )( usAddress - REG_COILS_START );
		switch ( eMode )
		{
			/* Read current values and pass to protocol stack. */
			case MB_REG_READ:
			while( iNCoils > 0 )
			{
				*pucRegBuffer++ = xMBUtilGetBits( ucRegCoilsBuf, usBitOffset,	( unsigned char )( iNCoils > 8 ? 8 : iNCoils ) );
				iNCoils -= 8;
				usBitOffset += 8;
			}
			break;

				/* Update current register values. */
			case MB_REG_WRITE:
			while( iNCoils > 0 )
			{
				xMBUtilSetBits( ucRegCoilsBuf, usBitOffset,	( unsigned char )( iNCoils > 8 ? 8 : iNCoils ),	*pucRegBuffer++ );
				iNCoils -= 8;
				usBitOffset += 8;
			}
			break;
		}

	}
	else
	{
		eStatus = MB_ENOREG;
	}
	return eStatus;
}


/**
  *****************************************************************************
  * @Name   : 操作离散寄存�???
  *
  * @Brief  : 对应功能�???0x02 -> eMBFuncReadDiscreteInputs
  *
  * @Input  : *pucRegBuffer:数据缓冲区,响应主机用
  *           usAddress:     寄存器地�???
  *           usNRegs:       操作寄存器个�???
  *
  * @Output : none
  *
  * @Return : Modbus状�?�信�???
  *****************************************************************************
**/
//eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
//{
//	pucRegBuffer = pucRegBuffer;

//	return MB_ENOREG;
//}

eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    short           iNDiscrete = ( short )usNDiscrete;
    USHORT  usBitOffset;

    /* Check if we have registers mapped at this  block. */
    if( ( usAddress >= REG_DISCRETE_START ) && ( usAddress + usNDiscrete <= REG_DISCRETE_START + REG_DISCRETE_SIZE ) )
    {
        usBitOffset = ( USHORT )( usAddress - REG_DISCRETE_START );
        while( iNDiscrete > 0 )
        {
            *pucRegBuffer++ =
            xMBUtilGetBits( usRegDiscreteBuf, usBitOffset,( UCHAR )( iNDiscrete > 8 ? 8 : iNDiscrete ) );
            iNDiscrete -= 8;
            usBitOffset += 8;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }
    return eStatus;
}
/* USER CODE END PFP */

新建变量estatus 前后说的这些添加内容必须夹在user code字段中,否则cubemx修改工程重新生成代码后,你修改的内容会消失
freemodbus移植进STM32(包含HAL库和标准库两种方法)
初始化、使能
freemodbus移植进STM32(包含HAL库和标准库两种方法)
因为前面在串口初始化中,串口选择是被我写死的,不能通过这里的第三个形参去选择使用串口几,但是通过简单修改可以实现自由配置

最后在main函数中启动轮询就可以了
freemodbus移植进STM32(包含HAL库和标准库两种方法)文章来源地址https://www.toymoban.com/news/detail-454760.html

最后你把想传出去的数据放在各个寄存器中,外部modbus主机就可以查询到你放入寄存器的数据了

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
//输入寄存器内容
uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
//输入寄存器起始地址
uint16_t usRegInputStart = REG_INPUT_START;

//保持寄存器内容
uint32_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x147b,0x3f8e,0x147b,0x400e,0x1eb8,0x4055,0x147b,0x408e};
//保持寄存器起始地址
uint16_t usRegHoldingStart = REG_HOLDING_START;

//线圈状态
uint8_t ucRegCoilsBuf[REG_COILS_SIZE / 8] = {0x01,0x02};
//离散输入状态
uint8_t usRegDiscreteBuf[REG_DISCRETE_SIZE / 8] = {0x01,0x02};

uint8_t testfalg=0;

extern unsigned char NUM [];
/* USER CODE END PV */

到了这里,关于freemodbus移植进STM32(包含HAL库和标准库两种方法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • stm32标准库和HAL库的对比学习3.《学习外部中断EXIT和应用》

            本人是大一的学生,学习了一段时间的stm32,此系列博客为个人的学习笔记,方便个人复习,如有错误或问题,非常非常欢迎大家来大力指正。 简单用文字说一下原理。 如果先要清楚了解建议去b站看一下keysking大佬的教程,很有趣易懂( 本视频的部分图也来自keys

    2024年01月19日
    浏览(44)
  • stm32标准库和HAL库的对比学习4.《学习时钟源,时钟树与内部时钟和外部时钟的用法》

            本人是大一的学生,学习了一段时间的stm32,此系列博客为个人的学习笔记,方便个人复习,如有错误或问题,非常非常欢迎大家来大力指正。         简单用文字说一下原理。         如果先要清楚了解建议去b站看一下keysking大佬的教程,很有趣易懂(本

    2024年02月21日
    浏览(41)
  • 单片机移植freemodbus主机(STM32、GD32、瑞萨、国民技术等)

    从github下载:https://github.com/armink/FreeModbus_Slave-Master-RTT-STM32 无法下载或者下载太慢可以用资源下载,无需积分。freeModbus主机源码下载 示例代码 参考从机代码创建 将FreeModbus主机源代码拷贝到工程中间件-第三方库-freemodbus源码库:即MiddlewaresThird_PartyFreeModbusMaster文件夹中。

    2024年02月11日
    浏览(42)
  • 使用标准库和HAL库的STM32单片机进行串口通信/解决因例程为HAL库的传感器,而其他模块都是标准库,需要将数据用串口传送给标准库的单片机的相关问题

    (本文使用STM32F103C8T6,在CubeMX里演示用的是RBT6,但实际上引脚是一样的)         本文 着重解决一个大工程中,某些传感器的例程是HAL库的,而其他模块(或算法)都是标准库,导致难以移植的问题。 本文的解决方法是:使用一片单片机用HAL库(CubeMX)配置例程,然后

    2024年02月06日
    浏览(59)
  • 【STM32通讯系列--串口通讯】使用标准库、HAL库实现任意长度数据的收发(包含帧头、帧尾校验,配套完整开源程序)

    【数据组成】串口的通讯协议由开始位,数据位,校验位,结束位构成。 【数据结构】一般以一个低电平作为一帧数据的起始,接着跟随 8 位或者 9 位数据位,之后为校验位,分为奇校验,偶校验和无校验,最后以一个先高后低的脉冲表示结束位,长度可以设置为 0.5,1,

    2024年02月14日
    浏览(43)
  • STM32基于HAL库和STM32CubeMX的实时操作系统FreeRtOS开发

    1、FreeRTOS RTOS是一类操作系统,µC/OS,FreeRTOS,RTX,RT-Thread 等这些都是RTOS 类的操作系统 FreeRTOS 是众多RTOS 类操作系统中的一种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行,FreeRTOS 也不仅仅局限于在微控制器中使用。就单从文件数量上来看FreeRTOS 要比µC/OS 少得多

    2024年02月21日
    浏览(60)
  • 基于gd32f103移植freemodbus master 主栈

    1.移植freemodbus master需要先移植RT-Thread操作系统 GD32F103C8T6移植 RTT Nano 教程-CSDN博客 2.移植freemodbus master协议栈 在移植了RTT以后,我们需要移植就只有串口相关的函数 移植freemodbus master协议栈具体步骤 下载移植freemodbus master协议栈 源码 添加协议栈文件 向mdk添加头文件路径 修改

    2024年01月18日
    浏览(46)
  • 【HAL库】STM32+ESP8266+Onenet+MQTT,极简工程,hal库移植。

    ESP8266通过MQTT协议连接Onenet。从标准库移到了HAL库,过程有点麻烦,整了一天。做完后整理了一下,这个极简的工程,方便以后开发,也希望能帮助到大家,节约时间。 代码工程: https://github.com/wyfroom/ESP8266-Onenet-MQTT 该份代码硬件配置: 板子:STM32F103C8T6最小系统板。 外设:

    2024年02月03日
    浏览(50)
  • HAL库和标准库的区别

    本文回答来源于chat gpt4,非原创,也是我初学过程中所遇到的问题,答案分享给大家,如有侵权请联系删除: HAL 库(Hardware Abstraction Layer,硬件抽象层)和标准库(Standard Peripheral Library,标准外设库,又称为 SPL)都是 STM32 微控制器的固件库。它们的主要区别在于结构和抽象

    2024年02月07日
    浏览(32)
  • STM32之HAL、LL和标准库

    我们在进行STM32开发的时候,使用寄存器进行开发的终究是少数,大多数人还是习惯用库函数进行开发。到目前为止,有标准外设库、HAL库、LL库 三种。本文将分别介绍以下三种库,便于大家区分。 标准库(Standard Peripheral Library)是STMicroelectronics提供的最基本的库。它提供了

    2024年02月13日
    浏览(36)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包