main.c
1 | //*****************************************************************************
| 2 | //*
| 3 | //* LED fading test
| 4 | //* uses exponential PWM settings to achive visual linear brightness
| 5 | //*
| 6 | //* ATmega32 @ 8 MHz
| 7 | //*
| 8 | //*
| 9 | //*****************************************************************************
| 10 | #ifndef F_CPU
| 11 | /* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
| 12 | F_CPU im Makefile definiert werden, eine nochmalige Definition
| 13 | hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
| 14 | #ifndef/#endif
| 15 |
| 16 | Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
| 17 | verwendet wird und dort eine andere, nicht zur Hardware passende
| 18 | Taktrate eingestellt ist: Dann wird die folgende Definition
| 19 | nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
| 20 | von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
| 21 | noch nicht definiert: */
| 22 | #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 16000000"
| 23 | #define F_CPU 16000000UL // Systemtakt in Hz - Definition als unsigned long beachten >> Ohne ergeben Fehler in der Berechnung
| 24 | #endif
| 25 |
| 26 | #define BAUD 9600UL // Baudrate
| 27 |
| 28 | // Berechnungen
| 29 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
| 30 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
| 31 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
| 32 |
| 33 | #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
| 34 | #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
| 35 | #endif
| 36 |
| 37 |
| 38 |
| 39 | #include <inttypes.h>
| 40 | #include <avr/io.h>
| 41 | #include <util/delay.h>
| 42 | #include <avr/pgmspace.h>
| 43 |
| 44 | // global variables
| 45 |
| 46 | uint16_t pwmtable_16[256] PROGMEM = {0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
| 47 | 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
| 48 | 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6,
| 49 | 6, 7, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11,
| 50 | 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 17,
| 51 | 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
| 52 | 29, 31, 32, 33, 35, 36, 38, 40, 41, 43, 45,
| 53 | 47, 49, 52, 54, 56, 59, 61, 64, 67, 70, 73,
| 54 | 76, 79, 83, 87, 91, 95, 99, 103, 108, 112,
| 55 | 117, 123, 128, 134, 140, 146, 152, 159, 166,
| 56 | 173, 181, 189, 197, 206, 215, 225, 235, 245,
| 57 | 256, 267, 279, 292, 304, 318, 332, 347, 362,
| 58 | 378, 395, 412, 431, 450, 470, 490, 512, 535,
| 59 | 558, 583, 609, 636, 664, 693, 724, 756, 790,
| 60 | 825, 861, 899, 939, 981, 1024, 1069, 1117,
| 61 | 1166, 1218, 1272, 1328, 1387, 1448, 1512,
| 62 | 1579, 1649, 1722, 1798, 1878, 1961, 2048,
| 63 | 2139, 2233, 2332, 2435, 2543, 2656, 2773,
| 64 | 2896, 3025, 3158, 3298, 3444, 3597, 3756,
| 65 | 3922, 4096, 4277, 4467, 4664, 4871, 5087,
| 66 | 5312, 5547, 5793, 6049, 6317, 6596, 6889,
| 67 | 7194, 7512, 7845, 8192, 8555, 8933, 9329,
| 68 | 9742, 10173, 10624, 11094, 11585, 12098,
| 69 | 12634, 13193, 13777, 14387, 15024, 15689,
| 70 | 16384, 17109, 17867, 18658, 19484, 20346,
| 71 | 21247, 22188, 23170, 24196, 25267, 26386,
| 72 | 27554, 28774, 30048, 31378, 32768, 34218,
| 73 | 35733, 37315, 38967, 40693, 42494, 44376,
| 74 | 46340, 48392, 50534, 52772, 55108, 57548,
| 75 | 60096, 62757, 65535};
| 76 |
| 77 |
| 78 | /*
| 79 | * Timer0 starten.
| 80 | *
| 81 | */
| 82 | void init_pwm_timer0 (){
| 83 | PORTD = (0 << PD6) | (1 << PD7);
| 84 | TCCR0 = (1 << WGM01)|(1 << WGM00) //Fast PWM
| 85 | |(1 << COM01)|(0 << COM00) //Set OC0 on compare match, clear OC0 at BOTTOM,
| 86 | |(0 << CS02) |(0 << CS01) |(1 << CS00); //clkI/O/(No prescaling)
| 87 |
| 88 | }
| 89 |
| 90 | /*
| 91 | * Time1 (16Bit) starten
| 92 | */
| 93 | void init_pwm_timer1 (){
| 94 | TCCR1A = _BV(COM1A1) | !_BV(COM1A0) // Both PWM outputs set at TOP,
| 95 | | _BV(COM1B1) | !_BV(COM1B0) // clear on compare match
| 96 | | !_BV(FOC1A) | !_BV(FOC1B) // PWM mode, can't force output
| 97 | | _BV(WGM11) | !_BV(WGM10); // Fast PWM, TOP = ICR1
| 98 |
| 99 | TCCR1B = !_BV(ICNC1) | !_BV(ICES1) // Disable input capture noise canceler,
| 100 | // edge select to negative.
| 101 | | _BV(WGM13) | _BV(WGM12) // Fast PWM, TOP = ICR1
| 102 | | !_BV(CS12) | _BV(CS11) | _BV(CS10); // clk(i/o) / 1024
| 103 |
| 104 | ICR1 = 0xFFFF; // TOP for PWM, full 16 Bit
| 105 |
| 106 | TCCR1B &= ~0x7; // clear clk setting
| 107 | TCCR1B |= 1; // precaler 1 -> ~122 Hz PWM frequency
| 108 |
| 109 | }
| 110 |
| 111 |
| 112 | /*
| 113 | * Timer2 starten
| 114 | */
| 115 | void init_pwm_timer2 (){
| 116 | TCCR2 = (1 << WGM21)|(1 << WGM20) //Fast PWM
| 117 | |(1 << COM21)|(0 << COM20) //Set OC0 on compare match, clear OC0 at BOTTOM,
| 118 | |(0 << CS22) |(0 << CS21) |(1 << CS20); //clkI/O/(No prescaling)
| 119 |
| 120 | }
| 121 |
| 122 | /*
| 123 | * Initialisieren der Timer des ATMega32
| 124 | */
| 125 | void INIT_Timer () {
| 126 | init_pwm_timer0();
| 127 | init_pwm_timer1();
| 128 | init_pwm_timer2();
| 129 | }
| 130 |
| 131 | /*
| 132 | * Einfaches Steuern der 3 PWMs
| 133 | */
| 134 | void DIM_Leds(uint16_t delay){
| 135 | int i;
| 136 | PORTD |= (1 << PD6);
| 137 | for(i=0; i<=255; i++){
| 138 | OCR0=i;
| 139 | OCR2=i;
| 140 | OCR1A = pgm_read_word(pwmtable_16+i);
| 141 | _delay_loop_2(delay);
| 142 | }
| 143 | PORTD &= (0 << PD6);
| 144 |
| 145 | for (i=255; i>=0; i--){
| 146 | OCR0=i;
| 147 | OCR2=i;
| 148 | OCR1A = pgm_read_word(pwmtable_16+i);
| 149 | _delay_loop_2(delay);
| 150 | }
| 151 |
| 152 | }
| 153 | /*
| 154 | * USART aktivieren.
| 155 | * Baudrate wird über defines ermittelt
| 156 | */
| 157 | void USART_Init()
| 158 | {
| 159 | UCSRB = 0x00;// Stop USART
| 160 | /* Set baud rate */
| 161 | UBRRH = UBRR_VAL >> 8;
| 162 | UBRRL = UBRR_VAL & 0xFF;
| 163 | /* Enable receiver and transmitter */
| 164 | UCSRB = (1<<TXEN); // Zum Empfangen (1<<RXEN) |
| 165 | /* Set frame format: 8data, 1stop bit */
| 166 | UCSRC |=
| 167 | (1<<URSEL)| //muss gesetzt sein
| 168 | (0<<UMSEL)| //Asynchrone Schnittstelle
| 169 | (0<<UPM1)| //no parity
| 170 | (0<<UPM0)| //no parity
| 171 | (0<<USBS)| //one stop bit only
| 172 | (1<<UCSZ1)| //8-bit mode
| 173 | (1<<UCSZ0)| //8-bit mode
| 174 | (0<<UCPOL); //Write this to zero in asynchronous mode
| 175 |
| 176 |
| 177 | }
| 178 |
| 179 |
| 180 |
| 181 | void USART_Transmit(unsigned char data )
| 182 | {
| 183 | /* Wait for empty transmit buffer */
| 184 | while ( !( UCSRA & (1<<UDRE)) );
| 185 | /* Put data into buffer, sends the data */
| 186 | UDR = data;
| 187 | }
| 188 |
| 189 | /* puts ist unabhaengig vom Controllertyp */
| 190 | void USART_Puts (char *s)
| 191 | {
| 192 | while (*s)
| 193 | { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
| 194 | USART_Transmit(*s);
| 195 | s++;
| 196 | }
| 197 | }
| 198 |
| 199 | /*
| 200 | * Testen der Ports.
| 201 | * Alle LEDs an
| 202 | *
| 203 | */
| 204 | void CHECK_Ports(){
| 205 | int i;
| 206 |
| 207 | PORTD |= (1 << PD5) | (1 << PD6) | (1 << PD7);
| 208 | PORTB |= (1 << PB3);
| 209 | for (i = 0; i < 256; i++ ){
| 210 | _delay_loop_2(30000);
| 211 | }
| 212 | }
| 213 |
| 214 | int main(void)
| 215 | {
| 216 | int16_t step_time=8000; // delay in millisecond for one fading step
| 217 |
| 218 | DDRD = (1 << PD5) | (1 << PD6) | (1 << PD7) ; // LED uses OC1A OC1A
| 219 | DDRB = (1 << PB3);
| 220 |
| 221 | CHECK_Ports();
| 222 | INIT_Timer();
| 223 | // Testausgabe auf dem Terminal
| 224 | USART_Init();
| 225 | _delay_loop_2(64000);
| 226 | USART_Puts("Yeah!! It Works");
| 227 | USART_Puts(" -- Aber was ist falsch");
| 228 | // test all fading routines
| 229 | while(1) {
| 230 | DIM_Leds(step_time);
| 231 | };
| 232 |
| 233 | return 0;
| 234 | }
|
|