Since the PlatformIO serial monitor is set to a baudrate of 9600, the USART baudrate should be 9600 in order to monitor data:
#define FOSC 16000000
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
To be able to use USART, the receiver (RX) and the transmitter (TX) should be enable:
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<UCSZ02);
The frame format should have a 9th bit to distinguish between address frames and data frames (+1 stop bits):
UCSR0C = (1<<UCSZ00)|(1<<UCSZ01);
Frame | start | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | stopbit |
---|---|---|---|---|---|---|---|---|---|---|---|
Bit | LOW | X | X | X | X | X | X | X | X | X | HIGH |
To send an Address Frame:
send_addr(SLAVE1_ADDR);
Waits until the channel is empty, saves 1 into TXB8 (9 bit) and sends address:
...
while (!(UCSR0A & (1<<UDRE0)));
UCSR0B |= (1<<TXB80);
UDR0 = addr;
To send a Data Frame:
send_data(ON);
...
send_data(OFF);
Waits until the channel is empty, saves 0 into TXB8 (9 bit) and sends data:
...
while (!(UCSR0A & (1<<UDRE0)));
UCSR0B &= ~(1<<TXB80);
UDR0 = data;
To receive, call:
get_data(&ADDRESS or &DATATYPE):
Waits for until receives something and checks if one of these error occur:
- Frame Error
- Data OverRun
...
while (!(UCSR0A & (1<<RXC0)));
if (UCSR0A & ((1<<FE0)|(1<<DOR0)))
return ERROR;
After checking errors appearance, ninth bit is filtered from UCSR0B register and it is returned. The parameter buffer is updated with new received data from UDR0:
...
ninthbit = (ninthbit >> 1) & 0x01;
*buffer = UDR0;
return ninthbit;
LED and RS485 Enable Pin is setup as an Output.
pinMode(LED_PIN, OUTPUT);
pinMode(WREN_PIN, OUTPUT);
To read the digital values of the DIP Switch, pull-up resistors are enable and node address is calculated:
pinMode(ADDR0_PIN, INPUT_PULLUP);
pinMode(ADDR1_PIN, INPUT_PULLUP);
pinMode(ADDR2_PIN, INPUT_PULLUP);
pinMode(ADDR3_PIN, INPUT_PULLUP);
ADDR = digitalRead(ADDR0_PIN) | digitalRead(ADDR1_PIN)<<1 | digitalRead(ADDR2_PIN)<<2 | digitalRead(ADDR3_PIN)<<3;
In case of master address, the pull-up resistors connected to the buttons are enable and the RS485 enable pin (WREN_PIN) is set to 1, in order to be able to send data to the slaves:
if (ADDR == MASTER_ADDR) {
pinMode(BUT1_PIN, INPUT_PULLUP);
pinMode(BUT2_PIN, INPUT_PULLUP);
digitalWrite(WREN_PIN, HIGH);
}
On the other hand, the Multi-processor Communication Mode is disable, the LED is turned off and the RS485 enable pin (WREN_PIN) is set to 0, in order to be able to receive data from the master:
/* SLAVE */
else
{
/* Multi-processor Communication Mode */
UCSR0A = (1<<MPCM0);
digitalWrite(LED_PIN, LOW);
digitalWrite(WREN_PIN, LOW);
}
This method allows to distinguish between address and datatype frames. When a node is considered addressed, the multi-processor communication mode is enable, it only receives datatype commands and discards address frames, until multi-processor communication mode is disable:
...
/* If address received from master matches the local address set by the DIP switches. */
/* ADDRESSED */
if (ADDR_R == ADDR) {
/* Multi-processor Communication Mode ENABLE */
UCSR0A &= 0xfe;
/* Received frames are all of datatype format, addressed ones are discarded */
/* Multi-processor Communication Mode DISABLE */
UCSR0A |= (1<<MPCM0);
}
The LED is turned on and turned off by received ON and OFF (from the master), respectively, with value 255 and 127. This received value is shifted 7 bits to have a value between 0 and 1, in order to command the LED:
...
digitalWrite(LED_PIN, data>>7 & 0x01);
...
This circuit was designed to be easily tested and programmed. In addition to the mandatory requirements, a FT232 interface, a AVR ISP and a 5V voltage regulator was added as optional requirements.
- The FT232 interface will allow testing Rx and Tx communications using a FTDI chip connected to a USB port, using a computer to track results.
- The ISP interface will allow uC to be programmed.
- 5V Voltage regulator (7805) allows acceptance of higher input voltages (up to 12V) without compromising the system behavior.
- Trace's width: 0.3mm. Able to handle 1A through the circuit.
- Crystal Capacitors (22pF) were changed to ceramic to match crystal performance requirements.