-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathmain.c
100 lines (87 loc) · 2.62 KB
/
main.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
/* Software ("bit-bang") UART Transmitter (8 data bits, 1 stop bit, no parity)
for Attiny24A/44A/84A using the internal 8MHz oscillator as clock source
(c) 2018 Marcel Meyer-Garcia
see LICENCE.txt
*/
/* NOTE: since the internal 8MHz oscillator is not very accurate, the value for OCR0A can be tuned
to achieve the desired baud rate (nominal value is 103)
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// change these to use another pin
#define TX_PORT PORTB
#define TX_PIN PB0
#define TX_DDR DDRB
#define TX_DDR_PIN DDB0
volatile uint16_t tx_shift_reg = 0;
void UART_tx(char character)
{
uint16_t local_tx_shift_reg = tx_shift_reg;
//if sending the previous character is not yet finished, return
//transmission is finished when tx_shift_reg == 0
if(local_tx_shift_reg){return;}
//fill the TX shift register witch the character to be sent and the start & stop bits (start bit (1<<0) is already 0)
local_tx_shift_reg = (character<<1) | (1<<9); //stop bit (1<<9)
tx_shift_reg = local_tx_shift_reg;
//start timer0 with a prescaler of 8
TCCR0B = (1<<CS01);
}
void UART_tx_str(char* string){
while( *string ){
UART_tx( *string++ );
//wait until transmission is finished
while(tx_shift_reg);
}
}
void UART_init(){
//set TX pin as output
TX_DDR |= (1<<TX_DDR_PIN);
TX_PORT |= (1<<TX_PIN);
//set timer0 to CTC mode
TCCR0A = (1<<WGM01);
//enable output compare 0 A interrupt
TIMSK0 |= (1<<OCF0A);
//set compare value to 103 to achieve a 9600 baud rate (i.e. 104µs)
//together with the 8MHz/8=1MHz timer0 clock
/*NOTE: since the internal 8MHz oscillator is not very accurate, this value can be tuned
to achieve the desired baud rate, so if it doesn't work with the nominal value (103), try
increasing or decreasing the value by 1 or 2 */
OCR0A = 103;
//enable interrupts
sei();
}
int main(void)
{
UART_init();
while(1)
{
UART_tx_str("Hello world!\n");
_delay_ms(100);
}
return 0;
}
//timer0 compare A match interrupt
ISR(TIM0_COMPA_vect )
{
uint16_t local_tx_shift_reg = tx_shift_reg;
//output LSB of the TX shift register at the TX pin
if( local_tx_shift_reg & 0x01 )
{
TX_PORT |= (1<<TX_PIN);
}
else
{
TX_PORT &=~ (1<<TX_PIN);
}
//shift the TX shift register one bit to the right
local_tx_shift_reg >>= 1;
tx_shift_reg = local_tx_shift_reg;
//if the stop bit has been sent, the shift register will be 0
//and the transmission is completed, so we can stop & reset timer0
if(!local_tx_shift_reg)
{
TCCR0B = 0;
TCNT0 = 0;
}
}