1 | #define F_CPU 16000000UL
|
2 | #define BAUDRATE 9600
|
3 | #define BAUD_CONST (((F_CPU/(BAUDRATE*16UL)))-1)
|
4 |
|
5 | #include <avr/io.h>
|
6 | #include <avr/interrupt.h>
|
7 | #include <util/delay.h>
|
8 | #include <stdio.h>
|
9 |
|
10 | volatile uint8_t ready = 0;
|
11 | volatile uint16_t result;
|
12 |
|
13 | // USART
|
14 | void USART_Init() {
|
15 | UBRR0H = (BAUD_CONST >> 8);
|
16 | UBRR0L = BAUD_CONST;
|
17 | UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
|
18 | }
|
19 |
|
20 | void USART_Transmit(unsigned char data) {
|
21 | while(!(UCSR0A & (1<<UDRE0))) ;
|
22 | UDR0 = data;
|
23 | }
|
24 |
|
25 | // ADC
|
26 | void ADC_Init() {
|
27 | ADCSRA |= (1<<ADEN); // ADC on
|
28 | ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // set prescaler to 128
|
29 | }
|
30 |
|
31 | uint8_t ReadValue(uint8_t adc_value) {
|
32 | uint8_t d_value;
|
33 |
|
34 | ADMUX = adc_value;
|
35 | _delay_ms(5);
|
36 |
|
37 | ADCSRA |= (1<<ADSC); // start first conversion
|
38 |
|
39 | while (ADCSRA & (1<<ADSC)) ; // wait until the conversion is over
|
40 |
|
41 | d_value = ADC >> 2;
|
42 |
|
43 | return (d_value < 250) ? d_value : 0;
|
44 | }
|
45 |
|
46 | // Timer1
|
47 | ISR(TIMER1_CAPT_vect) {
|
48 | static uint16_t value1, value2;
|
49 |
|
50 | if(TCCR1B & (1<<ICES1)) {
|
51 | value1 = ICR1;
|
52 | TCCR1B &= ~(1<<ICES1); // now waiting for falling edge
|
53 | }
|
54 | else {
|
55 | value2 = ICR1;
|
56 | TCCR1B |= (1<<ICES1); // now waiting for raising edge
|
57 | result = value2 - value1;
|
58 | ready = 1; // ready to print the duty cycle
|
59 | }
|
60 | }
|
61 |
|
62 |
|
63 | int main(void)
|
64 | {
|
65 | const unsigned char DutyCycle[] = "Duty cycle in percentage: ";
|
66 | unsigned char IntToString[3];
|
67 | int percentage;
|
68 |
|
69 | DDRD |= (1<<DDD5); // OC0B set as output (LED)
|
70 |
|
71 | USART_Init();
|
72 | ADC_Init();
|
73 |
|
74 | // Timer0
|
75 | TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00); // clear OC0A and OC0B on compare match, Fast PWM
|
76 | TCCR0B |= (1<<WGM02)|(1<<CS01)|(1<<CS00); // prescaler set to 64
|
77 | OCR0A = 249; // frequency is now 1 kHz
|
78 |
|
79 | // Timer1
|
80 | TCCR1B |= (1<<ICES1)|(1<<CS11)|(1<<CS10); // waiting for raising edge, prescaler set to 64, 250 kHz frequency
|
81 | TIMSK1 |= (1<<ICIE1); // Capture-Interrupt on
|
82 |
|
83 | sei();
|
84 |
|
85 | while (1)
|
86 | {
|
87 | OCR0B = ReadValue(0b01000000);
|
88 |
|
89 | if(ready) {
|
90 | cli();
|
91 |
|
92 | percentage = (result / 1000.0) * 100;
|
93 | sprintf((char*)IntToString, "%d", percentage);
|
94 |
|
95 | for(int i = 0; DutyCycle[i] != '\0'; i++)
|
96 | USART_Transmit(DutyCycle[i]);
|
97 |
|
98 | for(int i = 0; IntToString[i] != '\0'; i++)
|
99 | USART_Transmit(IntToString[i]);
|
100 |
|
101 | USART_Transmit('%');
|
102 | USART_Transmit('\r');
|
103 | USART_Transmit('\n');
|
104 |
|
105 | sei();
|
106 |
|
107 | ready = 0;
|
108 | }
|
109 |
|
110 | //_delay_ms(500);
|
111 | }
|
112 | }
|