2015-03-27 07:52 AM
Hello,
I am setting up communication via Modbus over RS232 line. The implementation works fine when no parity is implemented. But the specification dictates that even parity should be supported. The data reception is facilitated via DMA. To support the parity, I added the parity configuration. The word length is currently set to 8 bits. I receive the data correctly when parity is ON, but it sets a partiy error and I presume that my controller doesn't transmit the response because, 1. Party error is set 2. It does not insert the paity bit correctly and my terminal doesn't understand the received data and I get no result. I then looked further in the reference manual, and came across, Table Frame formats M bit| PCE bit | USART frame 0 | 0 | SB | 8 bit data | STB | 0 | 1 | SB | 7-bit data | PB | STB | 1 | 0 | SB | 9-bit data | STB | 1 | 1 | SB | 8-bit data PB | STB | Legends: SB: start bit, STB: stop bit, PB: parity bit. M bit is 0 for 8bit data length, 1 for 9bit data length PCE is 0 for parity disabled, 1 for parity enabled This means that I should set my word length to 9 bits in order to accomodate the parity bit, alongwith 8 data bits. But with this setting, my controller doesn't receive any data at all. I checked the osci, and it shows the bits correctly, i.e, |SB|8 Data Bits|PB|STB| Does anybody have any idea how/what may be causing a problem here? The configuration module looks like,USART_InitStructure.USART_BaudRate = p_baudrate;
if(p_parity == 0)
USART_InitStructure.USART_WordLength = p_wordlength;
else
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = p_stopbits;
USART_InitStructure.USART_Parity = (U16)((U16)p_parity<<8);
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init((USART_TypeDef *) USART_BASE, &USART_InitStructure);
Note: This configuration works for both Rx and Tx with no parity selected. So the pin and DMA configurations are correct.
2015-03-27 08:07 AM
I have no idea what your configuration constants are, or the hex values for the data that end up in the configuration registers.
You need to configure the interface in 9-bit mode, and correctly select Odd or Even parity depending on the requirements of the protocol, to get 8O1 or 8E1 modes. You probably want to write half-words to the data register, and mask the lower 8-bits when reading.2015-03-27 08:23 AM
Hi Clive,
The USART is correctly configured (as read from the SFR's). In the logically correct configuration, the word length is set to 9 bits, parity even (and enabled, ofcourse). I didnn't get what you meant by writing half-words. Can you elaborate on that further? Also, as I am making the Slave side, I cannot really control what the Master sends,i.e., I can do it for testing purposes, but to get it working properly, I cannot ask the user to modify the Modsbus specification so it fits in.2015-03-27 08:49 AM
And just for info, there is only one stop bit incase of even/odd parity. In case of no parity, 2 stop bits.
2015-03-27 09:13 AM
The USART is correctly configured (as read from the SFR's).
But you're complaining about errors, so either the configuration is wrong, or the signalling on the wire is. You're using some unspecified constants, and I don't see any scope output showing the signals. It's not working, so clearly something is wrong, I just don't have any solid information to work from. I'd start by explicitly setting the mode that should work.
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init((USART_TypeDef *) USART_BASE, &USART_InitStructure);
And confirm that works at a terminal level (8E1), perhaps using some echo back to prove successful two-way comms.
Then I'd look at where I was seeing data/parity error, and confine that on a scope or logic analyzer, so I understood the actual nature of the problem.
Half-Words, the USARTx->DR is 16-bit wide. So I'd perhaps configure DMA to do half-word transfers if required, so high order bits are zero. And when reading :
uint16_t data;
data = USARTx->DR & 0xFF; // Mask low order data bits, 8-bit wide