Hello,
Lastly I have whipped up a state machine based protocol for sending small frames using 9-bit address mode. Ft232rl, wrapped up in the MMusb232rl board, doesn't support this mode directly, so I am leaning on changing the parity bit to mark or space to simulate the address bit on the PC side. Everything works as a charm when I single step the program on the PC. Just on a sidenote, this program is coded in Qt using QtSerialPort. However, when I let the program run as it normally would in a production environment, the uC only receives several bytes out of the whole packet. I have observed the following happen. After reset, the uC receives 4 bytes out of 7. Then, I send the packet again, the uC gets 2/7. After that only 1/7th of every packet makes it to the uC, so only an address byte is being received and the state machine waits in the next state, which is 'wait for the number of parameters'. I think the most simple causes like incorrect wiring or voltage level mismatch can be ruled out right away, because single-stepping the PC program makes all the bytes come through successfully. That might suggest a baudrate mismatch, but I have checked hundreds of times and 9600 is used on both ends. That leaves, among others, a broken driver in the field. Right now I am using Linux kernel 3.9.9. I have also tried replacing literally every element of the system, including the 232 chip, the launchpad and moving the 232 chip over a breadboard to no avail. Unfortunately, I don't have access to neither a logic analyzer nor an oscilloscope. Has any of you encountered a similar problem? Below are the most important code snippets:
static inline void HW_UARTinit(void)
{
//---- Select and initialize pin to control RS485 transceiver direction ----------------
P1DIR |= BIT0;
P1OUT &= ~BIT0; // Set RS485 transceiver to receive.
//assign P1.1 and P1.2 to be used as Rx and Tx
P1SEL |= BIT1 + BIT2;
P1SEL2 |= BIT1 + BIT2;
//no parity,
//LSB first,
//8-bit data,
//one stop bit,
//address-bit multiprocessor mode,
//async mode
UCA0CTL0 |= UCMODE_2;
//select clock source - SMCLK,
//erroneous characters rejected and UCAxRXIFG is not set,
UCA0CTL1 |= UCSSEL_2;
//example prescaler settings:
//minimal error rate without external oscillator
//BRCLK == SMCLK == 1MHz
//baud == 9600
//UCBRx == 104
//UCBRSx == 1
//UCBRFx == 0
UCA0BR0 = 104;
UCA0BR1 = 0;
UCA0MCTL = UCBRS_1;
//release USCI for operation
UCA0CTL1 &= ~UCSWRST;
//enable Rx interrupt
IE2 |= UCA0RXIE;
}
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void){
//ISR(USART_RXC_vect)
stateTransition();
}
void stateTransition(void){
uint8_t receivedByte = 0;
if (HW_UARTaddress()){
vars.state = AWAIT_REQUEST_FETCH_ADDRESS;
}
// When TXC interrupt it may cause some problems and delays
if(vars.state < VALIDITY_CHECK){
receivedByte = HW_UARTget();
lumpBytesRcvd++;
}
...
}
inline static void _INIT(void) {
...
//DCO 1MHz
if (CALDCO_1MHZ == 0xFF || CALBC1_1MHZ == 0xFF) {
//calibration data was erased! we can't proceed
while (true);
} else {
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
}
//MCLK - default DCO/1
//SMCLK - default DCO/1
}
HW_UARTaddress() returns true if a last received byte has the address bit set, otherwise returns false. My last idea is that the internal RC oscillator is not stable enough to allow error-free reception of a few subsequent bytes, but that's not so likely.
Thanks to everyone who has taken time read this post. Any help will be much appreciated.