查看: 1440|回复: 0

[GD32F207开发板]Modbus with DMA

[复制链接]

该用户从未签到

发表于 2016-11-23 08:53:51 | 显示全部楼层 |阅读模式
分享到:
Modbus在工业仪表的应用非常广,连接PLC、HMI、PC等设备十分方便,最初用开源的freemodbus,这个功能比较完善,就是效率有点低,后来用的时间长了,就按照freemodbus的分层结构自己写了一份主从一体程序,移植到不同的平台主要就是硬件接口层了,拿到207i评估板后照例移植了过来。
207I的串口支持DMA,接收由于要同时操作定时器,暂时还没想到办法使用DMA功能,不过发送用DMA优化太合适不过了,这样可以减少大量的中断次数,特别是作为从机的时候。
报文发送程序示例:
uint8_t  mbWriteMultipleRegister( uint16_t DataAdd, uint8_t Len, uint16_t *Src )
{
  uint16_t DataIndex;
  WORD_VAL WToB;
  
if( (  Len > 123  ) || ( Len == 0 )  || ( ( 0xFFFF - DataAdd) < (Len - 1) ) )
return MB_ERR_OVERFLOW;
  if( (mbSndSt != MB_TX_IDLE) || (mbRcvSt != MB_RX_IDLE))  
  return MB_ERR_BUSY;
  mbAduBuff[0] = mbSlaveAddr;  
  mbAduBuff[1] = 0x10;
  WToB.Val  = DataAdd;
  mbAduBuff[2] = WToB.byte.HB;
  mbAduBuff[3] = WToB.byte.LB;
  mbAduBuff[4] = 0;
  mbAduBuff[5] = Len;
  mbAduBuff[6] = Len * 2;
  
  DataIndex  = 7;
  while(Len --)
  {
  WToB.Val  = *(Src ++);
  mbAduBuff[DataIndex ++] = WToB.byte.HB;
  mbAduBuff[DataIndex ++] = WToB.byte.LB;
  }
  
  mbRcvSt  = MB_RX_RCV;
  mbSndCnt  = DataIndex;
  mbAduSend();
  return MB_TX_IDLE;
}
//硬件接口程序如下
void mbAduSend()
{
  //添加crc并开启发送
  UINT16_VAL Data;
  
  if(mbState.bits.RTUMode)
  {
  Data.Val = usMBCRC16( mbAduBuff, mbSndCnt );
  mbAduBuff[mbSndCnt++] = Data.byte.LB;
  mbAduBuff[mbSndCnt++] = Data.byte.HB;
  pmbSndCur = mbAduBuff;
  mbPortEnable(DISABLE,ENABLE);  
  }
  
  mbSndSt = MB_TX_XMIT;
}
/*****************************************************************************//*!
*
* @brief  Uart En or Dis.
*  
* @param  none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
static void mbPortEnable( uint8_t xRxEnable, uint8_t xTxEnable )
{
volatile uint8_t u8Temp;

if(xRxEnable)
{
mbUART->CTLR1  &= ~((uint32_t)USART_CTLR1_TCIE);
mbUART->CTLR1  &= ~((uint32_t)USART_CTLR1_TBEIE);

U1RxEnable();
  
  mbUART->CTLR1  &= ~((uint32_t)USART_CTLR1_TEN);
mbUART->CTLR1  |= (uint32_t)USART_CTLR1_REN;

u8Temp  = mbUART->DR;
u8Temp  = mbUART->STR;
while((mbUART->STR & (USART_STR_ORE | USART_STR_RBNE)) != 0)
{
u8Temp  = mbUART->DR;
u8Temp  = mbUART->STR;
}

mbUART->CTLR1  |= USART_CTLR1_RBNEIE;
}
else if(xTxEnable)
{
mbUART->CTLR1  &= ~((uint32_t)USART_CTLR1_RBNEIE);

U1TxEnable();
  
mbUART->CTLR1  &= ~((uint32_t) USART_CTLR1_REN );
mbUART->CTLR1  |= (uint32_t)USART_CTLR1_TEN;

//mbSndCnt --;  //work without dma
//mbUART->DR  =  *(pmbSndCur ++);  //work without dma
//mbUART->CTLR1  |= (uint32_t)(USART_CTLR1_TBEIE);  //work without dma
  
  Uart1TxDma(mbAduBuff, mbSndCnt);
}
else
{
}
}
//DMA 处理程序
/*****************************************************************************//*!
*
* @brief  uart dma channel = 4.
*  
* @param  none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void Uart1TxDma(uint8_t *pData, uint16_t Len)
{
  DMA1_CHANNEL4->MBAR = (uint32_t)pData;
  DMA1_CHANNEL4->RCNT = Len;
  DMA1_CHANNEL4->CTLR |= DMA_CTLR_CHEN;
  __disable_irq();
  mbUART->CTLR3  |= ((uint32_t)USART_CTLR3_DENT);
  mbUART->STR  &= ~((uint32_t)(USART_STR_TC));
  __enable_irq();
}
/*****************************************************************************//*!
*
* @brief  uart dma channel4 isr.
*  
* @param  none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void DMA1_Channel4_IRQHandler()
{
  if(DMA1->IFR & DMA_IFR_TCIF4)
  {
  DMA1->ICR |= DMA_ICR_GIC4 | DMA_ICR_TCIC4 | DMA_ICR_HTIC4 | DMA_ICR_ERRIC4;
  
  mbSndCnt = 0;
  mbUART->CTLR3  &= ~((uint32_t)USART_CTLR3_DENT);
  DMA1_CHANNEL4->CTLR &= ~DMA_CTLR_CHEN;  
  mbUART->CTLR1  |= (uint32_t)(USART_CTLR1_TCIE);  //打开uart发送结束中断
  }
  else
  {
  //错误的中断
  DMA1->ICR |= DMA_ICR_GIC4 | DMA_ICR_TCIC4 | DMA_ICR_HTIC4 | DMA_ICR_ERRIC4;
  }
}
对于RS485接口,需要控制发送方向,这里在DMA结束后打开UART的 TC中断,在TC中断中切换总线方向
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /4 下一条

手机版|小黑屋|与非网

GMT+8, 2024-11-19 17:43 , Processed in 0.123133 second(s), 17 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.