Project

General

Profile

Statistics
| Revision:

root / trunk / common / rs485_poll.c @ 186

History | View | Annotate | Download (2.43 KB)

1
/**
2
 * @file rs485_poll.c
3
 * @brief RS485 implementation using UART hardware module and polling
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
#include <rs485_poll.h>
14

    
15
static void rs485_toggle_transmit(uint8_t state);
16

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

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

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

    
70
    // Enable writes and send
71
        rs485_toggle_transmit(RS485_TX_ON);
72
    UDR = data;
73

    
74
    // Waits until the transmit is done
75
    while(!(UCSRA & _BV(TXC)));
76
    rs485_toggle_transmit(RS485_TX_OFF);
77
    UCSRA |= _BV(TXC);
78

    
79
        return;
80
}
81

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