Project

General

Profile

Statistics
| Revision:

root / trunk / bootloader / rs485_sw.c @ 184

History | View | Annotate | Download (2.36 KB)

1
/**
2
 * @file rs485_sw.c
3
 * @brief RS485 implementation using UART hardware module and no interrupts
4
 *
5
 * This uses the AVR's UART hardware module but does polling rather than
6
 * interrupts to handle transmission and receiving. It assumes the use
7
 * of an external UART<->RS485 converter with the RXEN and TXEN pins tied
8
 * together.
9
 *
10
 * @author Kevin Woo <kwoo@2ndt.com>
11
 **/
12

    
13
/**
14
 * @brief Initializes the uart
15
 * @param baud The baudrate. Use the definitions in rs485_sw.h
16
 */
17
void rs485_init(uint16_t baud) {
18
        // Set baud rate
19
        UBRRH = (uint8_t)(baud>>8);
20
        UBRRL = (uint8_t)baud;
21
        
22
        // Enable RX/TX
23
        UCSRB = _BV(RXEN) | _BV(TXEN);
24
 
25
        // Enable the TXEN pin as output
26
        DDRD |= TX_EN;
27
    rs485_toggle_transmit(RS485_TX_OFF);
28
}
29

    
30
/**
31
 * @brief Non-blocking receive
32
 * 
33
 * Receives a byte from the UART if one exists. If none exist the function
34
 * will return an error code immediately. If there is a byte to receive,
35
 * it will be placed in a passed in pointer and return.
36
 *
37
 * @pre The RS485 TXEN line is not enabled
38
 * @param output_byte Byte to store the received message
39
 * @return 0 on success, negative if there is nothing to receive
40
 */
41
int8_t rs485_get_byte(uint8_t *output_byte) {
42
    if (UCSRA & _BV(RXC)) {
43
        *output_byte = UDR;
44
        return 0;
45
    } else {
46
        return -1;
47
    }
48
}
49

    
50
/**
51
 * @brief Blocking send
52
 *
53
 * Sends the byte in data onto the network. The function will block until
54
 * the transmit is complete so that the transmit enable line can be toggled
55
 * safely. It will wait until any current transmission completes before sending
56
 * and will wait until it completes before returning. The RS485 TX enable line
57
 * is automatically toggled by the function and should not be done so
58
 * outside the function.
59
 *
60
 * @param data The byte to send
61
 */
62
void rs485_send_byte(uint8_t data) {
63
        //Waits until current transmit is done
64
    while (!(UCSRA & _BV(UDRE)));
65

    
66
    // Enable writes and send
67
        rs485_toggle_transmit(RS485_TX_ON);
68
    UDR = data;
69

    
70
    // Waits until the transmit is done
71
    while(!(UCSRA & _BV(TXC)));
72
    rs485_toggle_transmit(RS485_TX_OFF);
73
    UCSRA |= _BV(TXC);
74

    
75
        return;
76
}
77

    
78
/**
79
 * @brief Toggles the RS485 TXEN line
80
 *
81
 * This function should not be used outside of this file
82
 *
83
 * @param state Whether to turn the pin on or off
84
 */
85
void rs485_toggle_transmit(uint8_t state) {
86
        if (state == RS485_TX_ON) {
87
                PORTD |= TX_EN;
88
        } else {
89
                PORTD &= ~TX_EN;
90
        }
91
}