-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
148 lines (119 loc) · 3.14 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
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
/*
* main.c
*
* Created on: 24/5/2016
* Author: boris
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#define F_CPU 8000000UL
#define UART_TXD_PIN PB0
#define UART_BAUD 9600
#define UART_BITS 12 // Total number of bits, including start, data, stop, inter-character space
#define TRIG_PIN PB1
#define ECHO_PIN PB2 // Use PB2 (INT0)
#define TRIG_LENGTH 30 // Trigger pulse length (uS)
#define US_PER_CM 58 // 58uS / cm
#define MEASURE_TIME_MS 50 // Measurement interval
volatile static uint8_t uart_out;
volatile static uint8_t uart_bit = 0;
volatile static uint8_t uart_data;
volatile static uint16_t pulse_length = 0;
volatile static uint16_t result;
// UART Timer Interrupt
ISR(SIG_OUTPUT_COMPARE0A) {
// Output a bit
if (uart_out & 1)
PORTB |= _BV(UART_TXD_PIN);
else
PORTB &= ~_BV(UART_TXD_PIN);
uart_bit--;
if (!uart_bit) { // Check if tx done
TIMSK &= ~_BV(OCIE0A); // Disable Interrupt TimerCounter0 Compare Match A
return;
}
if (uart_bit == UART_BITS - 1)
uart_out = uart_data; // Start bits transmitted, now goes the rest
else {
uart_out >>= 1;
uart_out |= 0x80; // Prepare 1s for stop bits
}
}
// Measurement Timer Interrupt
ISR(SIG_OUTPUT_COMPARE1A) {
pulse_length++;
}
// Echo Input Interrupt
ISR(SIG_INTERRUPT0) {
if (PINB & _BV(ECHO_PIN)) { // Pulse start
TCNT1 = 0;
pulse_length = 0;
} else // Pulse end
result = pulse_length;
}
void uart_setup(void) {
// GPIO configuration
DDRB |= _BV(UART_TXD_PIN); // Configure TxD pin as output
PORTB |= _BV(UART_TXD_PIN); // UART space is 1
// Timer 0 configuration
TCCR0A = _BV(WGM01); // CTC Mode
TCCR0B = _BV(CS01); // Clock = ClkI/O / 8
OCR0A = F_CPU / 8 / UART_BAUD; // Timer reload value
}
void sensor_setup(void) {
DDRB |= _BV(TRIG_PIN); // Trig pin is output
PORTB &= ~_BV(TRIG_PIN); // Set Trig to 0
DDRB &= ~_BV(ECHO_PIN); // Sensor pin is input
PORTB |= _BV(ECHO_PIN); // Enable pull-up resistor
// Timer 1 configuration
TCCR1 = _BV(CTC1) | _BV(CS12); // CTC Mode, Clock = ClkI/O / 8
OCR1C = US_PER_CM - 1;
TIMSK |= _BV(OCIE1A); // Enable Interrupt TimerCounter1 Compare Match A
// Setup INT0
MCUCR |= _BV(ISC00); // Interrupt on any logical change on INT0
GIMSK |= _BV(INT0); // Enable external pin interrupt
}
void uart_send(uint8_t data) {
if (uart_bit)
return;
uart_data = data;
uart_bit = UART_BITS;
uart_out = 0; // Start bit is logic 0
TIFR |= _BV(OCF0A); // Clear OCF0A by writing logic 1
TIMSK |= _BV(OCIE0A); // Enable Interrupt TimerCounter0 Compare Match A
}
void uart_puts(char *str) {
char *ptr;
for (ptr = str; *ptr; ptr++) {
while (uart_bit);
uart_send((uint8_t)*ptr);
}
while (uart_bit);
uart_send('\r');
while (uart_bit);
uart_send('\n');
}
void measure_distance(void) {
result = 0;
// Trig pulse
PORTB |= _BV(TRIG_PIN);
_delay_us(TRIG_LENGTH);
PORTB &= ~_BV(TRIG_PIN);
// Wait for echo
_delay_ms(MEASURE_TIME_MS);
if (result > 400)
result = 0;
}
int main(void){
static char res[8];
uart_setup();
sensor_setup();
sei();
while(1) {
measure_distance();
utoa(result, res, 10);
uart_puts(res);
}
}