我需要使用CC1310作为MODBUS-RTU的从设备,我必须采用定时器的时间来判断帧的结束,但是我采用9600波特率时,设置定时器为3.5ms判断帧结束,这时我只能接收小数据字节的数据帧,当进行大量数据的时候,还没有接收完成,定时器就产生了中断,判断帧结束了
一下是我的代码,
1、底层配置
/* * =============================== UART =============================== */ #include <ti/drivers/UART.h> #include <ti/drivers/uart/UARTCC26XX.h> UARTCC26XX_Object uartCC26XXObjects[CC1310_5x5BOARD_UARTCOUNT]; uint8_t uartCC26XXRingBuffer[CC1310_5x5BOARD_UARTCOUNT][1024]; const UARTCC26XX_HWAttrsV2 uartCC26XXHWAttrs[CC1310_5x5BOARD_UARTCOUNT] = {{.baseAddr= UART0_BASE,.powerMngrId= PowerCC26XX_PERIPH_UART0,.intNum= INT_UART0_COMB,.intPriority= 0,.swiPriority= 2,.txPin= CC1310_5x5BOARD_UART_TX,.rxPin= CC1310_5x5BOARD_UART_RX,.ctsPin= PIN_UNASSIGNED,.rtsPin= PIN_UNASSIGNED,.ringBufPtr= uartCC26XXRingBuffer[CC1310_5x5BOARD_UART0],.ringBufSize= sizeof(uartCC26XXRingBuffer[CC1310_5x5BOARD_UART0]),.txIntFifoThr= UARTCC26XX_FIFO_THRESHOLD_1_8,.rxIntFifoThr= UARTCC26XX_FIFO_THRESHOLD_2_8,.errorFxn= NULL} }; const UART_Config UART_config[CC1310_5x5BOARD_UARTCOUNT] = {{.fxnTablePtr = &UARTCC26XX_fxnTable,.object= &uartCC26XXObjects[CC1310_5x5BOARD_UART0],.hwAttrs= &uartCC26XXHWAttrs[CC1310_5x5BOARD_UART0]}, }; const uint_least8_t UART_count = CC1310_5x5BOARD_UARTCOUNT; /* * =============================== UDMA ===============================
2、串口初始化
/*********************************************************************************************** * Function:RS485_Usart_Init * Description:485串口初始化 * Input:uint32_t u32baudRate * Output: * Note(s): ***********************************************************************************************/ void RS485_Usart_Init(uint32_t u32baudRate) {//GPIO_setConfig(Board_PIN_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);//const char echoPrompt[] = "RS485_Usart_Init:\r\n";/* Call driver init functions */GPIO_init();{GPIO_setConfig(Board_GPIO_REDE0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH);GPIO_setConfig(Board_GPIO_REDE1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH);GPIO_setConfig(Board_GPIO_REDE2, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH);}UART_init();/* Create a UART with data processing off. */UART_Params_init(&uartParams);uartParams.baudRate = u32baudRate;uartParams.parityType = UART_PAR_NONE;uartParams.dataLength = UART_LEN_8;uartParams.stopBits = UART_STOP_ONE;uartParams.writeDataMode = UART_DATA_BINARY;uartParams.writeMode = UART_MODE_CALLBACK;uartParams.writeCallback = uartCallback;//uartParams.writeTimeout = UART_WAIT_FOREVER;uartParams.readDataMode = UART_DATA_BINARY;uartParams.readMode = UART_MODE_CALLBACK;uartParams.readCallback = uartReadCallback;uartParams.readTimeout = UART_WAIT_FOREVER;uart = UART_open(Board_UART0, &uartParams);if (uart == NULL){/* UART_open() failed */while (1);} //USART_SWITCH_TX //; // //UART_write(uart, echoPrompt, sizeof(echoPrompt)); //Delay_ms(1);USART_SWITCH_RX; //GPIO_write(Board_GPIO_REDE0, 0); //GPIO_write(Board_GPIO_REDE1, 0); //GPIO_write(Board_GPIO_REDE2, 0);Modbus_RegMap(); //modbus-rtu寄存器地址映射 }
3、串口接收回调
void uartReadCallback(UART_Handle handle, void *buf, size_t count)
{
//Led1Toggle();
UART_readCancel(handle);
usartControl.byteRxEndFlag = false;
if (usartControl.strRxCount < USART_MAX_RX_COUNT)
{
usartControl.RxBuf[usartControl.strRxCount] = ((uint8_t*) buf)[0];
usartControl.strRxCount++;
}
else
{
usartControl.strRxCount = 0;
usartControl.RxBuf[usartControl.strRxCount] = ((uint8_t*) buf)[0];
usartControl.strRxCount++;
}
stopTimer(); //关闭定时器
//gpTimerClose();
//timerSet((float)usartControl.strRxCount * 1.04 + 8); //配置为4ms
myGpTimerInit(usartControl.strRxCount + 1);
openTimer(); //开启定时器
UART_read(uart, &input, 1);
return;
}
4、定时器函数
/***********************************************************************************************
* Function :myGpTimerInit
* Description : 定时器初始化
* Input :uint32_t timerValue
* Output :
* Note(s) :
***********************************************************************************************/
void myGpTimerInit(float timerValue)
{
/* Open the GPTimer driver */
GPTimerCC26XX_Params params;
if(timerValue == 0)
{
GPTimerCC26XX_Params_init(¶ms);
params.width = GPT_CONFIG_32BIT;
params.mode = GPT_MODE_ONESHOT_UP;
//params.mode = GPT_MODE_PERIODIC_UP;
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
hTimer = GPTimerCC26XX_open(Board_GPTIMER1A, ¶ms);
if(hTimer == NULL)
{
while(1);
}
}
if(timerValue != 0)
{
GPTimerCC26XX_setLoadValue(hTimer, 0);
GPTimerCC26XX_setLoadValue(hTimer, 191996);//定时3.5ms
/* Register the GPTimer interrupt */
GPTimerCC26XX_registerInterrupt(hTimer, myTimeoutCb, GPT_INT_TIMEOUT);
}
}
/***********************************************************************************************
* Function :openTimer
* Description : 开启定时器
* Input :
* Output :
* Note(s) :
***********************************************************************************************/
void openTimer(void)
{
/*
* Start the Receiver timeout timer (300ms) before
* EasyLink_receiveAsync enables the power policy
*/
//myGpTimerInit(300);
GPTimerCC26XX_start(hTimer);
}
/***********************************************************************************************
* Function :openTimer
* Description :关闭定时器
* Input :
* Output :
* Note(s) :
***********************************************************************************************/
void stopTimer(void)
{
GPTimerCC26XX_stop(hTimer);
//gpTimerClose();
}
void gpTimerClose(void)
{
GPTimerCC26XX_close(hTimer);
}
4、定时器中断回调
/***********************************************************************************************
* Function :rxTimeoutCb
* Description : 定时器超时回调函数
* Input :GPTimerCC26XX_Handle handle,GPTimerCC26XX_IntMask interruptMask
* Output :
* Note(s) :
***********************************************************************************************/
void myTimeoutCb(GPTimerCC26XX_Handle handle,GPTimerCC26XX_IntMask interruptMask)
{
/* Set the Timeout Flag */
//rxTimeoutFlag = true;
Led1Toggle();
// Led2Toggle();
//readCancel();
usartControl.strRxEndFlag = true;
/*
* Timer is automatically stopped in one-shot mode and needs to be reset by
* loading the interval load value
*/
//timerSet();
}
5、主循环调用
// while(1)
{
usartDataGet();
RTU_SlaverService();
}
Viki Shi:
“但是我采用9600波特率时,设置定时器为3.5ms判断帧结束,这时我只能接收小数据字节的数据帧,当进行大量数据的时候,还没有接收完成,定时器就产生了中断,判断帧结束了”
如果我理解正确,你所有的数据结束判断都是通过3.5ms?那大量数据时显然时间不够啊。modbus我没做过,是否可以通过外部中断?
Hwadong Chan:
程序架构貌似没有问题,你确定定时器是预想的3.5ms吗?适当延长一下时间看看。
注释的代码是什么情况,主循环都注释掉了。