-
Notifications
You must be signed in to change notification settings - Fork 0
/
uartsw_Tx.c
164 lines (132 loc) · 3.74 KB
/
uartsw_Tx.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*! \file uartsw2.c \brief Interrupt-driven Software UART Driver. */
//*****************************************************************************
//
// File Name : 'uartsw2.c'
// Title : Interrupt-driven Software UART Driver
// Author : Pascal Stang - Copyright (C) 2002-2004
// Created : 7/20/2002
// Revised : 4/27/2004
// Version : 0.6
// Target MCU : Atmel AVR Series (intended for the ATmega16 and ATmega32)
// Editor Tabs : 4
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#include <avr/io.h>
#include <avr/interrupt.h>
#include "global.h"
#include "timer.h"
#include "uartsw_Tx.h"
// Program ROM constants
// Global variables
// uartsw transmit status and data variables
static volatile u08 UartswTxBusy;
static volatile u08 UartswTxData;
static volatile u08 UartswTxBitNum;
// baud rate common to transmit and receive
static volatile u08 UartswBaudRateDiv;
// functions
//! enable and initialize the Tx software uart
void uartswInit_Tx(void)
{
// initialize the buffers
//uartswInitBuffers();
// initialize the ports
sbi(UARTSW_TX_DDR, UARTSW_TX_PIN);
// initialize baud rate
uartswSetBaudRate(9600);
// setup the transmitter
UartswTxBusy = FALSE;
// disable OC2 interrupt
cbi(TIMSK, OCIE2);
// attach TxBit service routine to OC2
timerAttach(TIMER2OUTCOMPARE_INT, uartswTxBitService);
// turn on interrupts
sei();
}
//! turns off software UART
void uartswOff_Tx(void)
{
// disable interrupts
cbi(TIMSK, OCIE2);
// detach the service routines
timerDetach(TIMER2OUTCOMPARE_INT);
}
void uartswSetBaudRate(u32 baudrate)
{
u16 div;
// set timer prescaler
if( baudrate > (F_CPU/64L*256L) )
//CHANGE THE ABOVE LINE IF CLOCK FREQ OF AVRLINX BOARD DIFFERS
//FROM AVRSAT
{
// if the requested baud rate is high,
// set timer prescalers to div-by-64
timer2SetPrescaler(TIMERRTC_CLK_DIV64);
div = 64;
}
else
{
// if the requested baud rate is low,
// set timer prescalers to div-by-256
timer2SetPrescaler(TIMERRTC_CLK_DIV256);
div = 256;
}
// calculate division factor for requested baud rate, and set it
//UartswBaudRateDiv = (u08)(((F_CPU/64L)+(baudrate/2L))/(baudrate*1L));
//UartswBaudRateDiv = (u08)(((F_CPU/256L)+(baudrate/2L))/(baudrate*1L));
UartswBaudRateDiv = (u08)(((F_CPU/div)+(baudrate/2L))/(baudrate*1L));
}
void uartswSendByte(u08 data)
{
// wait until uart is ready
while(UartswTxBusy);
// set busy flag
UartswTxBusy = TRUE;
// save data
UartswTxData = data;
// set number of bits (+1 for stop bit)
UartswTxBitNum = 9;
// set the start bit
cbi(UARTSW_TX_PORT, UARTSW_TX_PIN);//changed to cbi -JGM
// schedule the next bit
outb(OCR2, inb(TCNT2) + UartswBaudRateDiv);
// enable OC2 interrupt
sbi(TIMSK, OCIE2);
}
void uartswTxBitService(void)
{
if(UartswTxBitNum)
{
// there are bits still waiting to be transmitted
if(UartswTxBitNum > 1)
{
// transmit data bits (inverted, LSB first)
if( !(UartswTxData & 0x01) )
cbi(UARTSW_TX_PORT, UARTSW_TX_PIN);//changed to cbi -JGM
else
sbi(UARTSW_TX_PORT, UARTSW_TX_PIN);//changed to sbi -JGM
// shift bits down
UartswTxData = UartswTxData>>1;
}
else
{
// transmit stop bit
sbi(UARTSW_TX_PORT, UARTSW_TX_PIN);//changed to sbi -JGM
}
// schedule the next bit
outb(OCR2, inb(OCR2) + UartswBaudRateDiv); //WHAT IS INB?
// count down
UartswTxBitNum--;
}
else
{
// transmission is done
// clear busy flag
UartswTxBusy = FALSE;
// disable OC2 interrupt
cbi(TIMSK, OCIE2);
}
}