📄 modbus_ascii.c
字号:
#include "44B.h"
#include "Modbus_ASCII.h"
#include <string.h>
/****************************************************************/
//
// 接收模块
//
/****************************************************************/
static volatile RXDBUF RxdBuf;
//**********************************************************************
//功 能: 帧读指针加1
//**********************************************************************
static void pFrameRd_Inc(void)
{
if(RxdBuf.FrameCnt>0)
{
if(RxdBuf.pFrameRd == (FRAMEPT *volatile)&RxdBuf.FramePt[FrameBufLen-1])
{
RxdBuf.pFrameRd = (FRAMEPT *volatile)&RxdBuf.FramePt[0];
}
else
{
RxdBuf.pFrameRd++;
}
}
}
//**********************************************************************
//功 能: 以帧的Start指针为指针向接收缓冲区读一字节
//读1字节->清0->Start指针加1
//**********************************************************************
static volatile char FrameState_RdByte(void)
{
volatile char ch;
if(RxdBuf.ByteCnt>0)
{
ch = (volatile char)*RxdBuf.pFrameRd->Start;
*RxdBuf.pFrameRd->Start = (volatile char)0;
if(RxdBuf.pFrameRd->Start == (char *volatile)&RxdBuf.Buf[(RxdBufLen-1)])
{
RxdBuf.pFrameRd->Start = (char *volatile)&RxdBuf.Buf[0];
}
else
{
RxdBuf.pFrameRd->Start++;
}
return (ch);
}
else
{
return (0);
}
}
//**********************************************************************
//功 能: 读一帧数据
//**********************************************************************
int Modbus_GetFrame(char *pBuf)
{
int i;
int Len;
if(RxdBuf.FrameCnt>0)
{
Len = RxdBuf.pFrameRd->FrameLen;
if(*RxdBuf.pFrameRd->Start==FRAME_START && *RxdBuf.pFrameRd->End==FRAME_END)
{
for(i=0;i<Len;i++)
{
*pBuf++ = FrameState_RdByte();
}
RxdBuf.pFrameRd->Start = (char *volatile)0;
RxdBuf.pFrameRd->End = (char *volatile)0;
RxdBuf.pFrameRd->FrameLen = (volatile int)0;
pFrameRd_Inc();
rINTMSK |= BIT_URXD1;
RxdBuf.ByteCnt -= Len;
RxdBuf.FrameCnt--;
rINTMSK &= ~BIT_URXD1;
return (1);
}
else
{
for(i=0;i<Len;i++)
{
FrameState_RdByte();
}
RxdBuf.pFrameRd->Start = (char *volatile)0;
RxdBuf.pFrameRd->End = (char *volatile)0;
RxdBuf.pFrameRd->FrameLen = (volatile int)0;
pFrameRd_Inc();
rINTMSK |= BIT_URXD1;
RxdBuf.ByteCnt -= Len;
RxdBuf.FrameCnt--;
rINTMSK &= ~BIT_URXD1;
return (0);
}
}
else
{
return (0);
}
}
//**********************************************************************
//功 能: 删除接收缓冲区一字节数据
//删除数据->地址&计数器减1
//**********************************************************************
static void RxdBuf_DelByte(void)
{
if(RxdBuf.ByteCnt>0)
{
*RxdBuf.pWr = (volatile char)0;
if(RxdBuf.pWr == (char *volatile)&RxdBuf.Buf[0])
{
RxdBuf.pWr = (char *volatile)&RxdBuf.Buf[(RxdBufLen-1)];
}
else
{
RxdBuf.pWr--;
}
RxdBuf.ByteCnt--;
}
}
//**********************************************************************
//功 能: 向接收缓冲区写一字节数据
//地址加1->写数据->计数器加1
//**********************************************************************
static int RxdBuf_WrByte(const volatile char ch)
{
if(RxdBuf.ByteCnt<RxdBufLen-1)
{
if(RxdBuf.pWr == (char *volatile)&RxdBuf.Buf[(RxdBufLen-1)])
{
RxdBuf.pWr = (char *volatile)&RxdBuf.Buf[0];
}
else
{
RxdBuf.pWr++;
}
*RxdBuf.pWr = (volatile char)ch;
RxdBuf.ByteCnt++;
return (1);
}
else
{
return (0);
}
}
//**********************************************************************
//功 能: 帧写指针加1
//**********************************************************************
static void pFrameWr_Inc(void)
{
if(RxdBuf.FrameCnt<FrameBufLen-1)
{
if(RxdBuf.pFrameWr == (FRAMEPT *volatile)&RxdBuf.FramePt[(FrameBufLen-1)])
{
RxdBuf.pFrameWr = (FRAMEPT *volatile)&RxdBuf.FramePt[0];
}
else
{
RxdBuf.pFrameWr++;
}
}
}
//**********************************************************************
//功 能: 串口接收中断处理
//**********************************************************************
static void __irq UART1_ISR_Rxd(void)
{
int i;
char ch;
do
{
ch = RdURXH1();
switch(ch)
{
case FRAME_START:
if( RxdBuf.pFrameWr->Start == (char *volatile)0 )
{
RxdBuf.pFrameWr->End = (char *volatile)0;
RxdBuf.pFrameWr->FrameLen = (volatile int)0;
if(RxdBuf_WrByte((volatile char)ch))
{
RxdBuf.pFrameWr->FrameLen = (volatile int)1;
RxdBuf.pFrameWr->Start = (char *volatile)RxdBuf.pWr;
}
}
else
{
for(i=0;i<RxdBuf.pFrameWr->FrameLen;i++)
{
RxdBuf_DelByte();
}
RxdBuf.pFrameWr->Start = (char *volatile)0;
RxdBuf.pFrameWr->End = (char *volatile)0;
RxdBuf.pFrameWr->FrameLen = (volatile int)0;
if(RxdBuf_WrByte((volatile char)ch))
{
RxdBuf.pFrameWr->FrameLen = (volatile int)1;
RxdBuf.pFrameWr->Start = (char *volatile)RxdBuf.pWr;
}
}
break;
case FRAME_END:
if( RxdBuf.pFrameWr->Start != (char *volatile)0 )
{
if(RxdBuf.FrameCnt<FrameBufLen-1 && RxdBuf.ByteCnt<RxdBufLen-1)
{
RxdBuf_WrByte((volatile char)ch);
RxdBuf.pFrameWr->FrameLen++;
RxdBuf.pFrameWr->End = (char *volatile)RxdBuf.pWr;
pFrameWr_Inc();
RxdBuf.FrameCnt++;
}
else
{
for(i=0;i<RxdBuf.pFrameWr->FrameLen;i++)
{
RxdBuf_DelByte();
}
RxdBuf.pFrameWr->Start = (char *volatile)0;
RxdBuf.pFrameWr->End = (char *volatile)0;
RxdBuf.pFrameWr->FrameLen = (volatile int)0;
}
}
else
{
for(i=0;i<RxdBuf.pFrameWr->FrameLen;i++)
{
RxdBuf_DelByte();
}
RxdBuf.pFrameWr->Start = (char *volatile)0;
RxdBuf.pFrameWr->End = (char *volatile)0;
RxdBuf.pFrameWr->FrameLen = (volatile int)0;
}
break;
default:
if(RxdBuf.ByteCnt<RxdBufLen-1)
{
if(RxdBuf.pFrameWr->Start != (char *volatile)0)
{
if(RxdBuf_WrByte((volatile char)ch))
{
RxdBuf.pFrameWr->FrameLen++;
}
}
}
else
{
for(i=0;i<RxdBuf.pFrameWr->FrameLen;i++)
{
RxdBuf_DelByte();
}
RxdBuf.pFrameWr->Start = (char *volatile)0;
RxdBuf.pFrameWr->End = (char *volatile)0;
RxdBuf.pFrameWr->FrameLen = (volatile int)0;
}
break;
}
}while( (rUFSTAT1&0xf) >0 ); //若RxD_FIFO计数器为0退出
rI_ISPC = BIT_URXD1; //清除中断标志
}
//**********************************************************************
//功 能: Modbus数据接收缓冲区初始化
//**********************************************************************
static void Modbus_RxdBuf_Init(void)
{
memset((char *)&RxdBuf,0,sizeof(RxdBuf));
RxdBuf.pWr = (char *volatile)&RxdBuf.Buf[0];
RxdBuf.pFrameWr = (FRAMEPT *volatile)&RxdBuf.FramePt[0];
RxdBuf.pFrameRd = (FRAMEPT *volatile)&RxdBuf.FramePt[0];
RxdBuf.ByteCnt = (volatile int)0;
RxdBuf.FrameCnt = (volatile int)0;
RxdBuf.pFrameWr->FrameLen = (volatile int)0;
}
/****************************************************************/
//
// 发送模块
//
/****************************************************************/
static volatile TXDBUF TxdBuf;
//**********************************************************************
//功 能: 读指针加1
//**********************************************************************
static void TxdBuf_pRd_Inc(void)
{
if(TxdBuf.ByteCnt>0)
{
if(TxdBuf.pRd == (char *volatile)&TxdBuf.Buf[(TxdBufLen-1)])
{
TxdBuf.pRd = (char *volatile)&TxdBuf.Buf[0];
}
else
{
TxdBuf.pRd++;
}
}
}
//**********************************************************************
//功 能: 写指针加1
//**********************************************************************
static void TxdBuf_pWr_Inc(void)
{
if(TxdBuf.ByteCnt<TxdBufLen-1)
{
if(TxdBuf.pWr == (char *volatile)&TxdBuf.Buf[(TxdBufLen-1)])
{
TxdBuf.pWr = (char *volatile)&TxdBuf.Buf[0];
}
else
{
TxdBuf.pWr++;
}
}
}
//**********************************************************************
//功 能: 从发送缓冲区取一个byte
//**********************************************************************
static const volatile char TxdBuf_RdByte(void)
{
volatile char ch;
if(TxdBuf.ByteCnt>0)
{
ch = (volatile char)*TxdBuf.pRd;
*TxdBuf.pRd = (volatile char)0;
TxdBuf_pRd_Inc();
TxdBuf.ByteCnt--;
return (ch);
}
else
{
return (0);
}
}
//**********************************************************************
//功 能: 向发送收缓冲区写一字节数据
//写数据->地址加1->计数器加1->向串口发送寄存器写一字节->开发送中断
//**********************************************************************
static int TxdBuf_WrByte(const volatile char ch)
{
if(TxdBuf.ByteCnt<TxdBufLen-1)
{
*TxdBuf.pWr = ch;
TxdBuf_pWr_Inc();
*TxdBuf.pWr = (volatile char)0;
TxdBuf.ByteCnt++;
if( (rINTMSK&BIT_UTXD1) )
{
rUTXH1 = TxdBuf_RdByte();
rINTMSK &= ~BIT_UTXD1; //开UART0发送中断
}
return (1);
}
else
{
return (0);
}
}
//**********************************************************************
//功 能: 写一帧数据
//**********************************************************************
int Modbus_WrFrame(const volatile char *pBuf)
{
int StrLen;
if (!pBuf)
{
return (0);
}
StrLen = strlen((char *)pBuf);
if( (*pBuf!=FRAME_START) || (pBuf[StrLen-1]!=FRAME_END) )
{
return (0);
}
if( (TxdBuf.ByteCnt+StrLen) > (TxdBufLen-1) )
{
return (0);
}
for (; *pBuf; pBuf++)
{
TxdBuf_WrByte(*pBuf);
if (*pBuf == 0)
break;
}
return (1);
}
//**********************************************************************
//函 数 名: static void __irq UART0_ISR_Txd(void);
//功 能: 串口发送中断处理
//说 明:
//参 数:
//返 回 值:
//**********************************************************************
static void __irq UART1_ISR_Txd(void)
{
volatile char ch;
while( !(rUFSTAT1 & 0x200) && (ch=TxdBuf_RdByte()) ) //当TxD FIFO满或者TxLen为0时退出
{
rUTXH1 = ch;
}
if(!ch)
{
while(1)
{
if((rUTRSTAT1 & 0x04) == 0x04)
break;
}
rINTMSK |= BIT_UTXD1; //若这里不把中断关掉,TxD FIFO永远为空,也就是说中断永远都会发生!!
}
rI_ISPC = BIT_UTXD1;
}
//**********************************************************************
//功 能: Modbus数据发送缓冲区初始化
//**********************************************************************
static void UART1_TxdBuf_Init(void)
{
memset((char *)TxdBuf.Buf,0,sizeof(TxdBuf.Buf));
TxdBuf.pWr = (char *volatile)&TxdBuf.Buf[0];
TxdBuf.pRd = (char *volatile)&TxdBuf.Buf[0];
TxdBuf.ByteCnt = (volatile int)0;
}
/****************************************************************/
//
// 初始化模块
//
/****************************************************************/
//**********************************************************************
//功 能: 串口1中断注册
//**********************************************************************
static void UART1_INT_Init(void) //中断注册
{
pISR_URXD1 = (unsigned) UART1_ISR_Rxd;
pISR_UTXD1 = (unsigned) UART1_ISR_Txd;
}
/****************************************************************/
//函 数 名: void UART0_Init(int mclk,int baud);
//功 能: 串口接收中断处理
//说 明:
//参 数: mclk:系统时钟 baud:波特率
//返 回 值:
/****************************************************************/
void Modbus_Uart1_Init(int mclk,int baud)
{
rPCONC &= ~(0x0f<<24);
rPCONC |= (0x0f<<24); //GPE1 = TxD0,GPE2 = RxD0;
rPDATC |= (0x03<<12); //GPE1 = 1,GPE2 = 1;
rPUPC |= (0x03<<12); //GPE1\GPE2 Disable pull-up
rULCON1 = 0x03; //Normal,No parity,1 bit stop,8 bit data
rUCON1 = 0x02c5; //Tx Int->Level;Rx int->Pules;Rx time out enable;
//Error int enable;Tx mode->int;Rx mode->int;
rUFCON1 = 0xe7; //FIFO enable;RxD FIFO = 12 Bytes;Tx FIFO = 12 Bytes
rUMCON1 = 0x00;
rUBRDIV1=( (int)(mclk/16./baud + 0.5) -1 ); //设置波特率;
UART1_INT_Init(); //初始化串口0中断;
Modbus_RxdBuf_Init();
UART1_TxdBuf_Init();
rI_ISPC = BIT_URXD1;
rI_ISPC = BIT_UTXD1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -