I'm using two XMEGA256-A3BU's on XMEGA-A3BU Xplained boards. My goal is to make MPCM (Multiprocessor communication mode) possible between the two using their USART in synchronous mode.
They are physically connected so that the master's PC1 (SCL), PC2 (RXD) and PC3 (TXD) are connected to the slave's PC1 (SCL), PC3 (TXD) and PC2 (RXD) respectively.
I use ASF 3.33's "USART – serial service" to make the communication work.
Master's initialization code:
static usart_serial_options_t usart_options = {
.baudrate = 1200;
.charlength = USART_CHSIZE_8BIT_gc,
.paritytype = USART_PMODE_ODD_gc,
.stopbits = false
};
sysclk_enable_module(SYSCLK_PORT_C, PR_USART0_bm);
usart_serial_init(&USARTC0, &usart_options);
usart_set_mode(&USARTC0, USART_CMODE_SYNCHRONOUS_gc);
// Pin to set as output for clock signal.
ioport_configure_pin(IOPORT_CREATE_PIN(PORTC, 1), IOPORT_DIR_OUTPUT);
// Port to output clock signal on.
PORTCFG.CLKEVOUT = PORTCFG_CLKOUT_PC1_gc;
usart_set_rx_interrupt_level(&USARTC0, USART_RXCINTLVL_OFF_gc);
usart_set_tx_interrupt_level(&USARTC0, USART_TXCINTLVL_OFF_gc);
Slave's initialization code:
static usart_serial_options_t usart_options = {
.baudrate = 1200;
.charlength = USART_CHSIZE_8BIT_gc,
.paritytype = USART_PMODE_ODD_gc,
.stopbits = false
};
sysclk_enable_module(SYSCLK_PORT_C, PR_USART0_bm);
usart_serial_init(&USARTC0, &usart_options);
usart_set_mode(&USARTC0, USART_CMODE_SYNCHRONOUS_gc);
// Pin to set as input for clock signal.
ioport_configure_pin(IOPORT_CREATE_PIN(PORTC, 1), IOPORT_DIR_INPUT);
// Do not output the clock signal.
PORTCFG.CLKEVOUT = PORTCFG_CLKOUT_OFF_gc;
usart_set_rx_interrupt_level(&USARTC0, USART_RXCINTLVL_OFF_gc);
usart_set_tx_interrupt_level(&USARTC0, USART_TXCINTLVL_OFF_gc);
I use usart_serial_putchar(&USARTC0, buffer[i])
and usart_serial_getchar(&USARTC0, &buffer[i])
to send and receive data for testing, the final design will use DMA.
In order to make MPCM work (and make it possible to add more slaves to the bus), I know that I need to switch to the 1 start bit + 9 data bits + parity + 1 stop bit format, and I also know that somehow I should use these constants I found in iox256a3bu.h
file:
#define USART_MPCM_bm 0x02 /* Multi-processor Communication Mode bit mask. */
#define USART_MPCM_bp 1 /* Multi-processor Communication Mode bit position. */
Could someone help me out with some ASF sample code? What should I add to set the slave's own address, and where should I define on the master who I'm intending to send the message to?
Best Answer
I've spent a few hours on the problem, and fortunately it works now with one master and two slaves. It doesn't use DMA because I think it is impractical in this case, so I decided to use interrupts instead.
First I changed the USART's format to 9 bits, so the initialization method starts like this:
And I changed the interrupt level at its end:
Then I defined two methods to replace the
usart_serial_putchar(&USARTC0, buffer[i])
andusart_serial_getchar(&USARTC0, &buffer[i])
methods:After having these, I could setup the interrupt method on the slaves:
On the master I can use the
usart_send_mpcm_data(&USARTC0, usart_source[i], false);
method to send data, orusart_send_mpcm_data(&USARTC0, slave_address, true);
to change the target slave address. If the address is 0, then that's going to be a broadcast message, so all slaves will receive the data.