Problem in receiving data on UART2


#1

Hello,

I am trying to receive data from a microcontroller. I am having problem. There are some characters like ‘Z’ are inserted into received data. I have attached the code below and I would appreciate if someone could point out what is the mistake I have made. I am using Q24Plus

/***************************************************************************/
/* Section to Handle Data from MCU */
/***************************************************************************/
// Control handler for UART 2
bool FCM_UART2_CtrlHandler(adl_fcmEvent_e Event)
{
	s8 resultat;
	adl_atSendResponse ( ADL_AT_UNS,"FCM_UART2_CtrlHandler\r\n" );

	switch(Event)
	{
		case ADL_FCM_EVENT_FLOW_OPENNED:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_FLOW_OPENNED\r\n");
			resultat = adl_fcmSwitchV24State(FCM_UART2_handle, ADL_FCM_V24_STATE_DATA);
			break;

		case ADL_FCM_EVENT_FLOW_CLOSED:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_FLOW_CLOSED\r\n" );
			break;

		case ADL_FCM_EVENT_V24_DATA_MODE:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_V24_DATA_MODE\r\n");
			uart2Mode = UART_MODE_DATA;
			uart2Status = UART2_READY; // UART2 is now completely initialised
			break;

		case ADL_FCM_EVENT_V24_DATA_MODE_EXT:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_V24_DATA_MODE_EXT\r\n");
			break;

		case ADL_FCM_EVENT_V24_AT_MODE:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_V24_AT_MODE\r\n");
			uart2Mode = UART_MODE_AT;
			break;

		case ADL_FCM_EVENT_V24_AT_MODE_EXT:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_V24_AT_MODE_EXT\r\n");
			break;

		case ADL_FCM_EVENT_RESUME:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_RESUME\r\n");
			b_canSendDataToUart2 = TRUE;
			// sendBufToUart2();
			break;

		case ADL_FCM_EVENT_MEM_RELEASE:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_MEM_RELEASE\r\n");
			break;

		case ADL_FCM_EVENT_V24_DATA_MODE_FROM_CALL:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_V24_DATA_MODE_FROM_CALL\r\n");
			break;

		case ADL_FCM_EVENT_V24_AT_MODE_FROM_CALL:
			adl_atSendResponse ( ADL_AT_UNS,"ADL_FCM_EVENT_V24_AT_MODE_FROM_CALL\r\n");
			break;

		default:
			adl_atSendResponse ( ADL_AT_UNS,"DEFAULT\r\n");
			break;
	}
return(FALSE);
}

// Data handler for UART 2
bool FCM_UART2_DataHandler(u16 DataSize, u8 * Data)
{
	adl_atSendResponse ( ADL_AT_UNS,Data);
	return(TRUE);
}

// Subscribe to the UART2 FCM after a short delay
void tmrHandler_startFcmUart2( u8 ID )
{
	// Subscribe to the FCM for UART2
	FCM_UART2_handle = adl_fcmSubscribe ( ADL_FCM_FLOW_V24_UART2, FCM_UART2_CtrlHandler, FCM_UART2_DataHandler );

	adl_atSendResponse ( ADL_AT_UNS, "adl_fcmSubscribe UART2 return value: ");
	adl_atSendResponse ( ADL_AT_UNS, FCM_UART2_handle );
	adl_atSendResponse ( ADL_AT_UNS, "\r\n");

	if(FCM_UART2_handle < 0)
		adl_atSendResponse ( ADL_AT_UNS,"adl_fcmSubscribe UART2 failed\r\n" );
}

//----------------------------------------------------------------------------------------
// Check that OK is received after setting UART2 default speed
// If OK, wait, then subscribe to the FCM for UART2
//----------------------------------------------------------------------------------------
bool cmd_RspHandler_IPR(adl_atResponse_t * params)
{
	ascii buf[30];

	adl_atSendResponse ( ADL_AT_UNS, "cmd_RspHandler_IPR\r\n");

	wm_strRemoveCRLF(buf, params->StrData, params->StrLength);

	if ((!wm_strcmp(buf, "OK")) && (uart2Status == UART2_CHANGING_SPEED))
	{
		uart2Status = UART2_OPENING_FCM;
		// Must wait before subscribing to the FCM for UART 2,
		// otherwise the UART2 parameters are not set correctly
		// and the UART2 is not synchronised to the incomming data.
		adl_tmrSubscribe ( FALSE, 1, ADL_TMR_TYPE_100MS, tmrHandler_startFcmUart2 );
	}
	return FALSE;
}


//----------------------------------------------------------------------------------------
// Response handler after requesting/modifying UART2 status.
// If UART2 is closed then open it. Once open, then change speed.
// If it is already open, then leave it open and change speed.
//----------------------------------------------------------------------------------------
bool cmd_RspHandler_WMFM(adl_atResponse_t * params)
{
	ascii buf[30];

	wm_strRemoveCRLF(buf, params->StrData, params->StrLength);

	switch(uart2Status)
	{
		case UART2_GETTING_STATUS:
			if(buf[13] == '0') // "+WMFM: 0,2,x,0" ==> Closed
			{
				uart2Status = UART2_CLOSED_WAITING_OK;
			}
			else if(buf[13] == '1') // "+WMFM: 0,2,x,1" ==> Open
			{
				uart2Status = UART2_OPEN_WAITING_OK;
			}
			break;

		case UART2_CLOSED_WAITING_OK:
			if(!wm_strcmp(buf, "OK"))
			{
				uart2Status = UART2_OPENING_WAITING_OK;
				// By default, only UART 1 is open. UART 2 must be explicitly opened
				adl_atCmdCreate( "AT+WMFM=0,1,2", FALSE, ( adl_atRspHandler_t ) cmd_RspHandler_WMFM, "*", NULL );
			}
			break;

		case UART2_OPEN_WAITING_OK:
			if(!wm_strcmp(buf, "OK"))
			{
				uart2Status = UART2_CHANGING_SPEED;
				// Set default speed for UART 2
				adl_atCmdCreate("AT+IPR=4800", ADL_AT_PORT_TYPE( ADL_AT_UART2, FALSE ), (adl_atRspHandler_t) cmd_RspHandler_IPR, "*", NULL);
			}
			break;

		case UART2_OPENING_WAITING_OK:
			if(!wm_strcmp(buf, "OK"))
			{
				uart2Status = UART2_GETTING_STATUS;
				// startUart2(); // get status of UART2 again. Should be open now
			}
			break;
	}

	return FALSE;
}

void startUart2(void)
{
	// Get UART2 status first.
	// If we try to open it when all ready open, then an error is returned.
	// Similarly, if we try to close it when all ready closed, then an error is returned.
	// So check status first and then act accordingly.
	adl_atSendResponse ( ADL_AT_UNS, "startUart2: get status UART2\r\n" );
	uart2Status = UART2_GETTING_STATUS;
	adl_atCmdCreate( "AT+WMFM=0,2,2", FALSE, ( adl_atRspHandler_t ) cmd_RspHandler_WMFM, "*", NULL );
}

Thanks
Green


#2

I don’t think the data handler returns zero-terminated strings (check the doc to be sure). So if the memory at address Data+Datasize happens to contain a non-zero byte (and its content is random in theory), you’ll append random garbage at the end of your adl_sendResponse().


#3

Data is definitely not zero-terminated, since it can hold the byte value 0 as a databyte and not as string-terminator.


#4

Good point :smiley:


#5

Thank you all for the reply.

Would it be enough if I make sure that I just grab the exact datasize using substring

or should I do anything else ?


#6

I think you have a fundamental misunderstanding about strings in ‘C’?

The NUL character marks the end of the string;
The NUL character is, therefore, not possible anywhere within a string.

strncpy will not add the NUL if it wasn’t there to start with, and will stop at any NUL found before the specified size…


#7

The doc doesn’t specifically mention this.

However, as already noted, it has to support NUL bytes in the data, so it can’t be a string;

Also, the fact that separate pointer and size are given is a huge clue that it’s not a string… 8)

Having said that, the ADL User Guide does mis-use the term “string” in some places; eg, viewtopic.php?f=47&t=1682


#8

Thank you all for the help. String termination was the problem indeed.