blob: 9b3a881e7edf1f59bfc8677f2ae502acff299783 [file] [log] [blame]
adamdunkels573bc292003-10-01 08:04:03 +00001/**
2 * \file
3 * RS232 communication device driver for the MSP430.
4 * \author Adam Dunkels <adam@sics.se>
5 *
6 * This file contains an RS232 device driver for the MSP430 microcontroller.
7 *
8 */
9
10#include <io.h>
11#include <signal.h>
12
13#include "rs232.h"
14
15void beep(void);
16void blink(void);
17
18unsigned char lastchar, lastchar_changed;
19
20#define RECVBUF_SIZE 256
21
22static unsigned char recvbuf[RECVBUF_SIZE];
23static unsigned char recvbufptr1 = 0,
24 recvbufptr2 = 0;
25
26interrupt(UART1RX_VECTOR) rs232_rx_usart1(void)
27{
28 volatile unsigned char dummy;
29
30 /* Check status register for receive errors. */
31 if(URCTL1 & RXERR) {
32 /* Clear error flags by forcing a dummy read. */
33 dummy = RXBUF1;
34 } else {
35 recvbuf[recvbufptr1] = RXBUF1;
36 recvbufptr1 = (recvbufptr1 + 1) % RECVBUF_SIZE;
37 }
38}
39/*-----------------------------------------------------------------------------------*/
40/**
41 * Initalize the RS232 port.
42 *
43 * \param none Not used.
44 * \return An error value or RS_ERR_OK if initialization succeeded.
45 */
46/*-----------------------------------------------------------------------------------*/
47unsigned char
48rs232_init(char none)
49{
50 int j;
51
52
53 /* This code taken from the FU Berlin sources and reformatted. */
54
55#define DELTA 600
56
57 unsigned int compare, oldcapture = 0;
58 unsigned int i;
59
60 BCSCTL1 = 0xa4; /* ACLK is devided by 4. RSEL=6 no division for MCLK
61 and SSMCLK. XT2 is off. */
62
63 BCSCTL2 = 0x00; /* Init FLL to desired frequency using the 32762Hz
64 crystal DCO frquenzy = 2,4576 MHz */
65
66 WDTCTL = WDTPW + WDTHOLD; /* Stop WDT */
67 BCSCTL1 |= DIVA1 + DIVA0; /* ACLK = LFXT1CLK/8 */
68 for(i = 0xffff; i > 0; --i); /* Delay for XTAL to settle */
69
70 /* Set DCO for 2,4576 Mhz: */
71 CCTL2 = CCIS0 + CM0 + CAP; /* Define CCR2, CAP, ACLK */
72 TACTL = TASSEL1 + TACLR + MC1; /* SMCLK, continous mode */
73 while(1) {
74 while((CCTL2 & CCIFG) != CCIFG); /* Wait until capture occured! */
75 CCTL2 &= ~CCIFG; /* Capture occured, clear flag */
76 compare = CCR2; /* Get current captured SMCLK */
77 compare = compare - oldcapture; /* SMCLK difference */
78 oldcapture = CCR2; /* Save current captured SMCLK */
79
80 if(DELTA == compare) {
81 break; /* if equal, leave "while(1)" */
82 } else if(DELTA < compare) { /* DCO is too fast, slow it down */
83 DCOCTL--;
84 if(DCOCTL == 0xFF) { /* Did DCO role under? */
85 BCSCTL1--;
86 }
87 } else { /* -> Select next lower RSEL */
88 DCOCTL++;
89 if(DCOCTL == 0x00) { /* Did DCO role over? */
90 BCSCTL1++;
91 }
92 /* -> Select next higher RSEL */
93 }
94 }
95 CCTL2 = 0; /* Stop CCR2 function */
96 TACTL = 0; /* Stop Timer_A */
97
98
99
100 /* RS232 */
101 UCTL1 = CHAR; /* 8-bit character */
102 UTCTL1 = SSEL1; /* UCLK = MCLK */
103
104#define RS232_SPEED 57600
105
106 if(RS232_SPEED == 19200) {
107 /* Set RS232 to 19200 */
108 UBR01 = 0x80; /* 2,457MHz/19200 = 128 -> 0x80 */
109 UBR11 = 0x00; /* */
110 UMCTL1 = 0x00; /* no modulation */
111 } else if(RS232_SPEED == 38400) {
112 /* Set RS232 to 38400 */
113 UBR01 = 0x40; /* 2,457MHz/38400 = 64 -> 0x40 */
114 UBR11 = 0x00; /* */
115 UMCTL1 = 0x00; /* no modulation */
116 } else if(RS232_SPEED == 57600) {
117 UBR01 = 0x2a; /* 2,457MHz/57600 = 42.7 -> 0x2A */
118 UBR11 = 0x00; /* */
119 UMCTL1 = 0x5b; /* */
120 } else if(RS232_SPEED == 115200) {
121 UBR01 = 0x15; /* 2,457MHz/115200 = 21.4 -> 0x15 */
122 UBR11 = 0x00; /* */
123 UMCTL1 = 0x4a; /* */
124 }
125
126
127 ME2 |= (UTXE1 | URXE1); /* Enable USART1 TXD/RXD */
128 IE2 |= URXIE1; /* Enable USART1 RX interrupt */
129 BCSCTL1 &= ~(DIVA1 + DIVA0); /* remove /8 divisor from ACLK again */
130
131
132 return RS_ERR_OK;
133}
134/*-----------------------------------------------------------------------------------*/
135/**
136 * Configure the RS232 port.
137 *
138 * \param params RS232 parameters.
139 * \param parity Parity.
140 * \return An error value or RS_ERR_OK if configuration succeeded.
141 */
142/*-----------------------------------------------------------------------------------*/
143unsigned char
144rs232_params(unsigned char params, unsigned char parity)
145{
146 return RS_ERR_OK;
147}
148/*-----------------------------------------------------------------------------------*/
149/**
150 * Get a byte from the serial port.
151 *
152 * \param c A pointer to the location where the byte is to be stored.
153 *
154 * \return An error value or RS_ERR_OK. If no data is available, the
155 * function returns RS_ERR_NO_DATA which is not a fatal error.
156 */
157/*-----------------------------------------------------------------------------------*/
158unsigned char
159rs232_get(char *c)
160{
161 if(recvbufptr1 == recvbufptr2) {
162 return RS_ERR_NO_DATA;
163 }
164 *c = recvbuf[recvbufptr2];
165 recvbufptr2 = (recvbufptr2 + 1) % RECVBUF_SIZE;
166 return RS_ERR_OK;
167}
168/*-----------------------------------------------------------------------------------*/
169/**
170 * Transmit a byte over the serial port.
171 *
172 * \param c A pointer to the location where the byte is to be stored.
173 *
174 * \return An error value or RS_ERR_OK. If the transmission buffer was
175 * full, RS_ERR_OVERFLOW is returned.
176 */
177/*-----------------------------------------------------------------------------------*/
178unsigned char
179rs232_put(char c)
180{
181 /* Loop until the transmission buffer is available. */
182 while ((IFG2 & UTXIFG1) == 0);
183
184 /* Transmit the data. */
185 TXBUF1 = c;
186
187 return RS_ERR_OK;
188}
189/*-----------------------------------------------------------------------------------*/