Guten Tag liebe Gemeinde, ich habe ein Problem: ich habe relativ wenig Ahnung von Programmierung, daher fällt mir das sehr schwer und einen richtigen Ansatz habe ich auch nicht gefunden. Ich bin mir auch nicht sicher, ob sowas ähnliches schon mal Thema war im Forum, ich hab vieles Ähnliches gefunden, aber richtig schlau wurde ich daraus nicht. Bin was Programmieren angeht wirklich ein Noob. Für ein kleineres Projekt an der Uni ist meine Aufgabe, eine RGB-LED-Ansteuerung per Pulsweitenmodulation zu realisieren. Als Mikrocontroller verwenden wir einen Atmega 328, nebenbei arbeiten wir mit AVR Studio 4 und einem AVR Dragon. Für das Projekt soll der ADC des uC verschiedene "Potentiometerstellungen" einlesen und diesen verschiedene Werte zuordnen( welche dann für die "Stärke" der 3 Farben stehen, soweit ich das verstanden habe). Ich hab mich schon viele Nachmittage rangesetzt, aber es mangelt mir einfach an theoretischem Verständnis dafür. Deshalb bitte ich euch um Hilfe. Ich danke im Voraus! :) LG Max
:
Verschoben durch User
wir haben dafür im Unterricht schon COdes geschrieben.. verstanden habe ich diese aber dennoch nicht. Leider.
Woran haperts beim Verstehen? Hast du mal einen einfachen Beispielcode?
es hapert an allem ehrlich gesagt. ich komme mit Programmierung einfach nicht zurecht und Beispielcodes habe ich, aber nur für Blinken oder so. also nichts wirklich hilfreiches. ich kann auch nicht lesen, was in solchen Codes steht, weil ich es einfach nicht begreife. Wenn du sagst was für ein Code für den Ansatz nützlich wäre könnte ich ihn reinstellen :)
Maxx schrieb: > ich kann auch nicht lesen, was in solchen Codes steht, weil ich es > einfach nicht begreife. Die Angst davor lähmt Dich. Such Dir einen Leidensgenossen und fangt einfach an mit den Beispielcodes. Diese dann variieren, Effekte bestaunen. Dann verlierst Du die Angst davor.
Hallo Maxx, > ich kann auch nicht lesen, was in solchen Codes steht, weil ich es > einfach nicht begreife. Zeige mal ein Beispiel. rhf
google schrieb: > Diese dann variieren, Effekte > bestaunen. Hab grad gesehen, dass man mit dem Dragon debuggen kann. Also das auch nutzen, gucken, was mit dem Code passiert. Vor allem: ANFANGEN, nicht theoretisch erwägen ...
das ist leider wahr, die Angst davor lähmt mich wirklich.. und der Fakt, dass es so ein halbwegs anspruchsvolles Projekt(in meinen Augen) ist wirkt nicht gerade motivierender auf mich. Codes kann ich euch leider morgen ab 10:00 erst schicken. Ich hoffe ihr könnt mir dann helfen. Hab dann den ganzen Tag Zeit, vielleicht ihr ja auch. :) wäre super lieb. Bis dahin gucke ich weiter, versuche, was zu verstehen. vielleicht könnt ihr mir ja einen ungefähren Aufbau meines Codes liefer, a la anfangen mit Variablendeklaration, einer Funktion zum einlesen des Potis, eine Funktion, die diese Werte verarbeitet, dann die Funktion, die für das Erzeugen einer PWM zuständig ist, wessen Signal dann an die R,G,B- Elemente der LED's weitergegeben wird, usw.. Ich verstehe komischerweise genau, was dort passieren soll, wie es angeschlossen wird, was gemacht werden muss, nur hab ich halt sobald es um's Programmieren geht, wirklich keine Vorstellung, wie ich das anzustellen habe. Ich weiß, das ist peinlich, vor allem, wenn man sich stundenlang damit beschäftigt und es trotzdem nicht begreift...
Maxx schrieb: > vielleicht könnt ihr mir ja einen ungefähren Aufbau meines Codes liefer, > a la anfangen mit Variablendeklaration, einer Funktion zum einlesen des > Potis, eine Funktion, die diese Werte verarbeitet, dann die Funktion, > die für das Erzeugen einer PWM zuständig ist, wessen Signal dann an die > R,G,B- Elemente der LED's weitergegeben wird, usw.. Du hast doch ausreichend Beispielcodes ... sollen wir Deine Arbeit machen?
nein sollt ihr nicht. ich komme nur halt erst morgen an die Codes ran und hoffe, dass ihr mir dann helfen könnt. ich will halt nur heute irgendwas für das Projekt machen, direkt daran arbeiten kann ich aber erst morgen
Hey Maxx, ich bin seit noch nicht so langer Zeit mit meinem E-Technik Studium fertig und ich erinnere mich noch ziemlich gut an einige Kommilitonen, die mit Programmierung überhaupt nicht klargekommen sind. Ist halt nicht unbedingt jedermanns Sache. Ich kann dir nur den Rat geben; such dir einen Kommilitonen der ein Händchen dafür hat und lass dir von dem auf die Sprünge helfen. Hilfe aus der Ferne ist ziemlich mühselig und jemand der dir deine Arbeit macht, findest du hier bestimmt nicht (ist ja auch nicht Sinn des Studiums). Also ich verstehe die Aufgabenstellung wie folgt: 3 Potis an 3 ADC-Eingängen (Port A) und 3 LEDs an 3 PWM-Ausgängen (ggf. über Transistor/MOSFET/Treiber-IC). Was ich dir als Eckpunkte aber gerne gegen den Kopf werfe, ist wie ich dein Programm ganz grob aufbauen würde: Initialisierung (einmal am Programmanfang): 1. Ein- und Ausgänge konfigurieren (DDR Register) 2. ADC konfigurieren (Register siehe Datenblatt) 3. Timer als Dual-Slope PWM konfigurieren, welche Timer du dafür nimmst, hängt davon ab, an welchen Pins deine LEDs angeschlossen sind. 8-Bit Modus beim 16-Bit Timer wird wahrscheinlich reichen. Programmablauf in Endlosschleife: 1. ADC Kanal 1 auswählen 2. AD-Wandlung starten 3. Warten bis Wandlung abgeschlossen ist 4. Ergebnis der Wandlung abholen und um 2 Bits kürzen (10 Bit auf 8 Bit) 5. 8-Bit Ergebnis in das Compareregister des Timers für die 1. LED schreiben -> Schritte 1 bis 5 jetzt auch noch für Kanal 2 und 3 Wiederholen Das ist es im Prinzip schon. Kann man mit Spaghetticode machen, schöner wird es wenn du die 3 Schritte der Initialisierung in einzelne Funktionen steckst. Punkt 1 bis 3 der Endlosschleife würde ich auch in eine Funktion verpacken, die den ADC-Wert als uint16_t zurückgibt und den Kanal als uint8_t Parameter bekommt. Wenn du für 5. dann auch noch eine kleine Funktion mit Wert und Kanal als Parameter schreibst, kannst du die 3 Kanäle in einer for-Schleife abhandeln und musst nicht den gleichen Code 3-mal schreiben. Mfg Bimbo385
Was du heute schon machen solltest ist, dir im Datenblatt die Kapitel und Registerbeschreibungen vom ADC und den Timern durchzulesen, das hält sich in Grenzen. Druck dir die Kapitel am besten aus und schreib dir in die Registerbeschreibungen schon mal rein, wie die Bits für deinen Anwendungsfall sein müssen. Geh alle Bits einmal durch, dann hast du eigentlich auch verstanden wie der ADC und die Timer funktionieren. Wenn du dann die Registerwerte, die du raus hast, hier postest, findest sich vielleicht auch jemand, der dazu einen Kommentar abgibt ;-) Mfg Bimbo385
Danke!! ich werde mich damit beschäftigen, ich hoffe, dass das was wird! einiges habe ich noch nicht ganz verstanden, kannst du vielleicht auf folgende Dinge nochmal näher eingehen: Bimbo 3. schrieb: > 3. Timer als Dual-Slope PWM konfigurieren, welche Timer du dafür nimmst, > hängt davon ab, an welchen Pins deine LEDs angeschlossen sind. 8-Bit > Modus beim 16-Bit Timer wird wahrscheinlich reichen. was bedeutet DUal-Slope und wie lege ich einen Timer fest? ich hab immer nur was von Timer1 gelesen Bimbo 3. schrieb: > 1. ADC Kanal 1 auswählen - wie "wähle" ich den denn "aus" also mit welcher Funktion wird das gemacht? Bimbo 3. schrieb: > 2. AD-Wandlung starten - wie starte ich die mit welcher Funktion? Bimbo 3. schrieb: > 4. Ergebnis der Wandlung abholen und um 2 Bits kürzen (10 Bit auf 8 Bit) - wie kürze ich das? einfach die Variable minus 2 rechnen? Bimbo 3. schrieb: > 5. 8-Bit Ergebnis in das Compareregister des Timers für die 1. LED > schreiben - auch bitte erläutern, kann mir darunter leider nix vorstellen :/ tut mir wirklich leid, mir fehlt da wirklich jegliches Verständnis fürs Programmieren.. es fällt mir super schwer, mich da reinzuversetzen. Danke jedenfalls! bis auf die Punkte habe ich alles, denke ich, gut verstanden! das hat schon mal viel geholfen!!
Oha, da scheinen dir ja jegliche Grundlagen zu fehlen, das ist nichts was ich mit 3 Sätzen aufklären könnte. Arbeite dich erstmal durch die Tutorials, Link steht ja schon da. Die Timer (Der ATmega328 hat 3 davon) sind wie z.B. der ADC Teile des µControllers, welche auf dem Chip neben der eigentlichen ALU vorhanden sind und teils unabhängig arbeiten. Bei allen µP die ich kenne ist es so, dass solche Komponenten durch Konfigurationsregister eingestellt werden und dann mehr oder weniger automatisch etwas tun. Das Ergebnis kann man dann aus Statusregistern oder "Ergebnisregistern" auslesen. Außerdem kann man auch Interrupts auslösen lassen, aber das vergiss erstmal wieder. Für den Timer0 musst du jetzt z.B. die Register TCCR0A und TCCR0B (Timer/Counter Control Register A/B) schreiben. Darin gibt es Bits die bestimmen was der Timer/Counter tun soll. Also hoch oder runterzählen, mit welchem Takt und ob daraus z.B. ein PWM-Signal generiert werden soll. Welche Bits was machen Steht im Datenblatt des ATmega328 auf S. 105 und folgende. Hier mal eine init-Funktion es einem meiner Programme (Ist für einen ATmega2560) bei der ich mehrere Timer konfiguriere, nur das du mal siehst wie das aussehen kann. Zu meiner Schande habe ich hier binäre Zahlen in die Register geschrieben, sodass man zwangsläufig ins Datenblatt schauen muss um die Bedeutung zu erkennen.
1 | // This function initializes the timers TC1 & TC4 for 25.000 kHz PWM.
|
2 | // TC2 to an other PWM frequency (>20 kHz), TC5 for period measuring and TC 3 for tick generation
|
3 | void timer_init() |
4 | {
|
5 | // Three timers for PWM generation.
|
6 | TCCR1A = 0b10101000; // clear up, set down, phase and frequency correct PWM |
7 | ICR1 = (320 -1); // 16MHz / (2*320) = 25kHz |
8 | // maximum is 319 so 0 - 319 are allowed values
|
9 | TCCR1B = 0b00010001; // WGM: 8, 16 MHz |
10 | |
11 | |
12 | TCCR4A = 0b10101000; // clear up, set down, phase and frequency correct PWM |
13 | ICR4 = (320 -1); // 16MHz / (2*320) = 25kHz |
14 | // maximum is 319 so 0 - 319 are allowed values
|
15 | TCCR4B = 0b00010001; // WGM: 8, 16 MHz |
16 | |
17 | |
18 | TCCR2A = 0b10100001; // clear up, set down, phase correct PWM |
19 | // 16MHz / (2*256) = 31.25kHz
|
20 | // maximum is 255 so 0 - 255 are allowed values
|
21 | TCCR2B = 0b00000001; // WGM: 8, 16 MHz |
22 | |
23 | |
24 | |
25 | // TC5 for period measuring
|
26 | TCCR5A = 0b00000000; // no output compare WGM: normal |
27 | TCCR5B = 0b10000100; // input noise cancel, falling edge, prescaler = 256 |
28 | TIMSK5 = 0b00100001; // input capture and overflow interrupt enabled |
29 | |
30 | EICRA = 0b10100000; // INT2 and INT3 to falling edge |
31 | EICRB = 0b00001010; // INT4 and INT5 to falling edge |
32 | EIMSK = 0b00111100; // INT2-5 enable |
33 | |
34 | |
35 | // TC3 for 100 ms trigger
|
36 | TCCR3A = 0b00000000; // no output compare WGM: 12 CTC at ICR3 |
37 | OCR3A = 6249; // 16MHz / (256*6250) = 10Hz |
38 | TCCR3B = 0b00001100; // prescaler = 256 |
39 | TIMSK3 = 0b00000010; // overflow interrupt enabled |
40 | }
|
Guten Tag, Max hier danke erstmal für den hilfreichen Text! Ich hoffe, dass es mir weiterhilft! So ganz eine Vorstellung was ich dann im finalen Source Code schreiben soll habe ich aber dennoch nicht. Ich verstehe aber zumindest, was dort geschehen soll. Ich könnte jetzt sogar einige Codes schicken, von denen ich aber den richtigen Effekt nicht wirklich kenne. Vielleicht kannst du/ könnt ihr mir ja dann einiges zum Verständnis erläutern! MfG Max :)
Hallo Maxx, > Ich könnte jetzt sogar einige Codes schicken, von denen ich aber den > richtigen Effekt nicht wirklich kenne. Vielleicht kannst du/ könnt ihr > mir ja dann einiges zum Verständnis erläutern! Du erzählst uns jetzt seit zwei Tagen das du das alles nicht verstehst, zeigst aber nicht was du nicht verstehst. Wie soll man dir da helfen? Zeige endlich mal was du an Quellcodes hast und was du daran nicht verstehst. rhf
Hey, hier nun endlich ein Code, tut mir leid, ich war doch mehr im Stress als erwartet. dieser Code hier ist zB für mein Projekt relativ gut geeignet, den habe ich jedoch nicht selbst erstellt, sondern selbst gefunden. an dem würde ich mich orientieren, wenn ich ihn verstehen würde. ich habe auch noch einzelne Codes für einzelne Module wie zB pwm.c, aber erstmal dachte ich, schicke ich diesen, weil der viele Übereinstimmungen mit meinem Projekt hat. Ich würde euch ja auch selbstgemachte Codes schicken, aber die wären dann von mehr Fehlern geprägt. 'OC0A = PD.6 = Pin 12 - RGB LED_1 R 'OC0B = PD.5 = Pin 11 - RGB LED_2 R 'OC1A = PB.1 = Pin 15 - RGB LED_1 G 'OC1B = PB.2 = Pin 16 - RGB LED_2 G 'OC2A = PB.3 = Pin 17 - RGB LED_1 B 'OC2B = PD.3 = Pin 5 - RGB LED_1 B 'ADC0 = PC.0 = Pin 23 'ADC1 = PC.1 = Pin 24 'ADC2 = PC.2 = Pin 25 'ADC3 = PC.3 = Pin 26 'ADC4 = PC.4 = Pin 27 'ADC5 = PC.5 = Pin 28 $regfile = "m88adef.dat" $crystal = 8000000 $hwstack = 100 $swstack = 100 $framesize = 100 '$PROG &HFF,&HE2,&HDF,&HF9' generated. Take care that the chip supports all fuse bytes. Ddrb = &B11111111 'PortB = Ausgang Portb = &B00000000 'und auf low gesetzt Ddrc = &B00000000 'PortC = Eingang Portc = &B00000000 'und auf low gesetzt Ddrd = &B11111111 'PortD = Ausgang Portd = &B00000000 'und auf low gesetzt Rot_pwm1 Alias Ocr0a 'PWM-Output: Pin 12 Rot_pwm2 Alias Ocr0b 'PWM-Output: Pin 11 Gruen_pwm1 Alias Ocr1al 'PWM-Output: Pin 15 Gruen_pwm2 Alias Ocr1bl 'PWM-Output: Pin 16 Blau_pwm1 Alias Ocr2a 'PWM-Output: Pin 17 Blau_pwm2 Alias Ocr2b 'PWM-Output: Pin 05 Dim Adc0 As Byte Dim Adc1 As Byte Dim Adc2 As Byte Dim Adc3 As Byte Dim Adc4 As Byte Dim Adc5 As Byte Dim Rot_pwm1 As Byte Dim Rot_pwm2 As Byte Dim Gruen_pwm1 As Byte Dim Gruen_pwm2 As Byte Dim Blau_pwm1 As Byte Dim Blau_pwm2 As Byte Config Adc = Single , Prescaler = Auto , Reference = Avcc Start Adc Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up On Timer0 Timer0_pwm Enable Timer0 Config Timer1 = Pwm , Prescale = 1 , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up On Timer1 Timer1_pwm Enable Timer1 Config Timer2 = Pwm , Prescale = 1 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up On Timer2 Timer2_pwm Enable Timer2 Enable Interrupts Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.4 , E = Portb.6 , Rs = Portb.7 Config Lcd = 16 * 2 Cls Do Adc0 = Getadc(0) Adc1 = Getadc(1) Adc2 = Getadc(2) Adc3 = Getadc(3) Adc4 = Getadc(4) Adc5 = Getadc(5) Rot_pwm1 = Adc0 Gruen_pwm1 = Adc1 Blau_pwm1 = Adc2 Rot_pwm2 = Adc3 Gruen_pwm2 = Adc4 Blau_pwm2 = Adc5 Locate 1 , 1 Lcd " " ; Rot_pwm1 Locate 1 , 5 Lcd " " ; Gruen_pwm1 Locate 1 , 10 Lcd " " ; Blau_pwm1 Locate 2 , 1 Lcd " " ; Rot_pwm2 Locate 2 , 5 Lcd " " ; Gruen_pwm2 Locate 2 , 10 Lcd " " ; Blau_pwm2 Locate 1 , 1 Lcd " " ; Adc0 Locate 1 , 5 Lcd " " ; Adc1 Locate 1 , 10 Lcd " " ; Adc2 Locate 2 , 1 Lcd " " ; Adc3 Locate 2 , 5 Lcd " " ; Adc4 Locate 2 , 10 Lcd " " ; Adc5 Waitms 500 Cls Loop End Timer0_pwm: Rot_pwm1 = Adc0 Rot_pwm2 = Adc3 Return Timer1_pwm: Gruen_pwm1 = Adc1 Gruen_pwm2 = Adc4 Return Timer2_pwm: Blau_pwm1 = Adc2 Blau_pwm2 = Adc5 Return entnommen von: https://www.makerconnect.de/index.php?threads/adc-werte-f%C3%BCr-pwm-nutzen-rgb-led-ansteuerung.2860/
hier eine vorgegebene Datei: pwm.c /** * @brief pwm driver implementation, uses atmega328 timer * @author T.K. * @note This is a doxygen style comment block **/ /* avr gcc specific header files for uC I/O etc. */ #include <avr/io.h> #include "pwm.h" /** * @brief Init all PWM handling specific HW * @par none */ void PwmInit(void) { TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (1 << WGM11) | (0 << WGM10); TCCR1B = (0 << ICNC1) | (0 << ICES1) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10); TCNT1 = 0; OCR1A = 0; ICR1 = 0xffff; OCR1B = 0; #if 0 TCCR1A |= 0x43; TCCR1B |= 0x19; TCNT1 = 0; #endif DDRB |= 0x04; // PB2 to output } /** * @brief PWM duty cycle set function * @par none */ void PwmSetDuty(uint8_t duty) { uint16_t d; if (duty == 0) { PORTB |= 0x04; // set pin off TCCR1B &= ~0x07; // stop timer return; } if (duty == 100) { PORTB |= 0x04; // set pin on TCCR1B &= ~0x07; // stop timer return; } d = (0xffff/100) * duty; OCR1B = d; TCCR1B |= 0x01; // (re)start timer } /** * @brief * @par * @par * @par */
tick.c, obwohl ich mir nicht sicher bin, ob das hilfreich ist /** * @brief one msec tick timer driver implementation, uses atmega328 timer0 * @author T.K. * @note This is a doxygen style comment block **/ /* avr gcc specific header files for uC I/O etc. */ #include <avr/io.h> #include <avr/interrupt.h> #include "tick.h" /* reload value for timer0 counting up to MAX (0xff) at 20Mhz/256 for 1msec */ #define T0_RELOAD_1MSEC (0xff-78+1) /* global variables used by isr and applic */ volatile static uint8_t Keytimer; /* keys sampling cycle timer */ volatile static uint16_t Sectimer; /* one second counter (msecs) */ /** * @brief timer0 isr, gets called every 1msec * @par none */ ISR(TIMER0_OVF_vect) { TCNT0 = T0_RELOAD_1MSEC; Keytimer++; Sectimer++; } /** * @brief Init all msec tick Timer handling specific HW * @par none */ void TickInit(void) { /* 1 msec timer 0 init */ TCCR0B = 0x04; /* CPU clock/256 prescaler */ TCNT0 = T0_RELOAD_1MSEC; TIMSK0 = 0x01; /* enable T0 Overflow interrupt */ } /** * @brief Get the actual msecs counter * @par none */ uint16_t TickGetMsecs(void) { return (Sectimer); } /** * @brief Set the msecs counter * @par new counter value */ void TickSetMsecs(uint16_t val) { ISR_DISABLE(); Sectimer = val; ISR_ENABLE(); } /** * @brief Get the actual key debounce msecs counter * @par none */ uint16_t TickGetKeyMsecs(void) { return (Keytimer); } /** * @brief Set the key debounce msecs counter * @par new counter value */ void TickSetKeyMsecs(uint16_t val) { ISR_DISABLE(); Keytimer = val; ISR_ENABLE(); } /** * @brief * @par * @par * @par */
uart.c /** * @brief uart driver implementation * @author T.K. * @note This is a doxygen style comment block **/ /* avr gcc specific header files for uC I/O etc. */ #include <avr/io.h> #include <avr/interrupt.h> #include "uart.h" #define UART_RX_BUF_SIZE 16 static volatile uint8_t Rxbuf[UART_RX_BUF_SIZE]; static volatile uint8_t RxRidx; /* read idx from circular RX-Buffer */ static volatile uint8_t RxWidx; /* write idx to circular RX-Buffer */ static volatile uint8_t RxSema; /* number of chars waiting for read by application */ /** * @brief UART0 RxD Isr * @par none */ ISR (USART_RX_vect) { Rxbuf[RxWidx] = UDR0; RxWidx++; RxWidx &= (UART_RX_BUF_SIZE-1); RxSema++; } /** * @brief Init UART peripheral * @par none */ void UartInit(void) { #ifndef F_CPU #define F_CPU 20000000UL // Systemtakt in Hz - Definition als unsigned long beachten #endif #define BAUD 9600UL // gewünschte Baudrate // Berechnungen durch den C Preprocessor machen lassen ;o) #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler. #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010)) #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! #endif UBRR0H = UBRR_VAL >> 8; UBRR0L = UBRR_VAL & 0xFF; UCSR0B = (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0); UCSR0C = (1 << UCSZ01)|(1 << UCSZ00); // Asynchron 8N1 RxRidx = 0; RxWidx = 0; RxSema = 0; } /** * @brief Test if UART is free to send next char * @par none */ uint8_t UartTxAvailable(void) { uint8_t r; if ( (UCSR0A & 0x20) > 0 ) r = 1; else r = 0; return(r); } /** * @brief Test if a UART has a received char available * @par none */ uint8_t UartRxAvailable(void) { return(RxSema); } /** * @brief Send a char by UART * @par uint8_t char to be sent */ void UartPutc(uint8_t c) { UDR0 = c; } /** * @brief Send a string by UART * @par uint8_t* char to start of string to be sent */ void UartPutString(uint8_t* s) { while(*s) { if (UartTxAvailable()) { UartPutc(*s); s++; } } } /** * @brief Get a char from UART * @par none */ uint8_t UartGetc(void) { uint8_t r; r = Rxbuf[RxRidx]; RxRidx++; RxRidx &= (UART_RX_BUF_SIZE-1); if (RxSema > 0) RxSema--; return(r); } /** * @brief * @par * @par * @par */
und eine dazugehörige main.c, die ein Studienkollege erstellt hat: #include <avr/io.h> #include <util/delay.h> #define LED_PORT PORTC #define LED_PIN 0 #define LED_off() LED_PORT&=~_BV(LED_PIN) #define LED_on() LED_PORT|=_BV(LED_PIN) int main (void) { DDRC = 0b10000000; while (1) { LED_on(); _delay_ms(2); LED_off(); _delay_ms(8); } return(0); #include <avr/io.h> #include <avr/interrupt.h> #include "key.h" #include "pwm.h" #include "tick.h" #include "uart.h" #include "string.h" int main (void) { uint8_t keystate = 0; uint8_t str[50]; uint8_t str2[50]; uint8_t instr[16]; uint8_t dutyled = 50; uint8_t c; TickInit(); PwmInit(); UartInit(); ISR_ENABLE(); while(1) { if(TickGetKeyMsecs() >= 300) { TickSetKeyMsecs(0); if(UartRxAvailable()) { for(int i = 0; i < UartRxAvailable();i++) { str2[i] = UartGetc(); } sprintf((char*) &str[0],"%i\n", UartRxAvailable()); UartPutString(&str[0]); } } } }
Hallo Maxx, Mit welcher Proragmmiersprache arbeitet ihr? Der erst Quellcode ist in Basic (vermutlich BASCOM), die unteren Quellcodes sind in C geschrieben. > und eine dazugehörige main.c, die ein Studienkollege erstellt hat: Das sind aber 2 verschiedene main()-Routinen: einmal der Klassiker zum LED-Blinken und unten die main()-Routine für die PWM-Geschichte. Aber egal, was verstehst du nicht? rhf
Hey Roland! Wir arbeiten mit C in AVR Studio 4 und da ich mich damit nicht auskenne wusste ich auch nicht, dass der erste nicht in C geschrieben war, entschuldigung. Naja ich verstehe einfach die einzelnen Funktionen nicht, was diese bewirken und wie sie das tun. ich verstehe die Variablendeklarationen uint8_t keystate = 0; uint8_t str[50]; uint8_t str2[50]; uint8_t instr[16]; uint8_t dutyled = 50; uint8_t c; das danach sind sicherlich aufgerufene Funktionen aus den zugehörigen Header-Dateien die while Schleife ist dann schon schwieriger, die versteh ich nicht so wirklich. soll ich die dazugehörigen header mal reinstellen? bringt dieser code meinem Projekt überhaupt etwas? danke für die Hilfe :)
Hallo Maxx, > Wir arbeiten mit C in AVR Studio 4 > und da ich mich damit nicht auskenne wusste ich auch nicht, dass der > erste nicht in C geschrieben war, entschuldigung. Du brauchst dich nicht zu entschuldigen. Allerdings hat es keinen Zweck mit dir den Code durch zusprechen, wenn du den Unterschied zwischen BASIC und C nicht erkennst. Dein Problem ist das du noch nicht mal die absoluten Grundlagen verstanden hast und darüber hinaus offensichtlich auch dein Werkzeug nicht bedienen kannst. Nicht schlimm, das kann man alles lernen. Ein Forum wie dieses hier kann dir dabei aber nur wenig helfen, weil die Kommunikation viel zu umständlich und zeitraubend ist. Ich pflichte einem anderen Diskussionsteilnehmer bei und rate dir jemanden zu suchen, der mit dir zusammen mal ein paar Grundlagen und Beispiele durch geht. rhf
Hey Roland, ich hab den Unterschied mittlerweile erkannt. und einige Grundlagen beherrsche ich auch. Ich hab den ersten Quelltext nur überflogen und da sah er ähnlich aus. Jetzt wo ich ihn näher betrachtet habe, erkenne ich aus. Dennoch weiß ich nicht mal, wie ich bei meinem Projekt anfangen soll... ich finde, dass das Forum mir aber trotzdem viel weitergeholfen hat!Ich hab' dadurch bereits eine viel größere Vorstellung davon, wie ich mein Projekt zu gestalten habe. Also vielleicht kannst du mir ja mal sagen, welche Funktionen ich brauche, um mein Projekt so zu realisieren, wie ich muss? Vielleicht auch mit kurzer Beschreibung? Der gute Bimbo385 hat mir ja schon geholfen, einen groben Aufbau des Programms zu haben.
Hallo Maxx, > Dennoch weiß ich nicht mal, wie ich bei meinem Projekt anfangen soll... Ja, das merkt man. Du musst dich zuerst mit der Programmiersprache vertraut machen. Vorher brauchst du mit deinem Projekt gar nicht anfangen. Kauf dir ein Buch zu C, installiere dir ein C-Entwicklungssystem, was einfaches wie z.B. LCC: http://www.cs.virginia.edu/~lcc-win32/ und programmiere die Beispiel im Lehrbuch nach. Das hört sich jetzt erst mal nach viel Vorarbeit an und das ist es auch. Aber es führt kein Weg daran vorbei. Erst wenn du in C eine gewisse Sicherheit erlangt hast, solltest du mit dem einfachsten Beispiel auf dem AVR-Kontroler beginnen (das ist das LED-Blink-Programm deiner ersten main()-Funktion). Wenn das läuft, weißt du das deine AVR-Entwicklungsumgebung (also AVR Studio 4) funktioniert. > Also vielleicht kannst du mir ja mal sagen, welche Funktionen ich > brauche, um mein Projekt so zu realisieren, wie ich muss? Du musst deine Aufgabe in ganz einfache Teilaufgaben zerlegen: Als erstes würde ich ein Programm schreiben, das mittels des AD-Wandlers einen Potentiometerwert einliest und z.B. über die serielle Schnittstelle (UART) ausgibt (damit man sieht ob die Werte plausibel sind). Das erweiterst du dann so, das 3 Potis ausgelesen und angezeigt werden. Dann würde ich eine Funktion schreiben, die ein PWM-Signal ausgibt und mit diesem Signal erst mal nur eine einfache LED ansteuern. Funktioniert das, erweiterst du das auf 3 LEDs, so das du dann mit deinen 3 Potis (je eins für R, G und B) diese 3 LEDs in der Helligkeit steuern kannst. Eine ganz wichtige Hilfe ist https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial und https://www.mikrocontroller.net/articles/AVR-Tutorial Da steht im Prinzip (ADC-, UART- und PWM-Programmierung) alles drin, was du zum Lösen deiner Aufgabe wissen musst. rhf
Moin Maxx, bin wieder da, musste mal ein bisschen Rennauto fahren die letzten Tage ;-) Also wenn ich dich dich richtig verstehe fehlen dir schon die Grundlagen zur C-Programmierung (while-Schleife). Die Programmiersprache C ist grundsätzlich erstmal unabhängig von dem zu programmierendem System/µC. Du solltest eigentlich wenn du im Studium an so einem Projekt sitzt, vorher irgendeine Grundlagenvorlesung C-Programmierung gehabt haben, in der so Sachen wie Schleifen, Deklarationen, Funktionen, Typendefinitionen, Strukturen, Arrays und Pointer usw. erklärt werden. Ich gebe gerne zu, dass auch ich nicht jede Syntax immer im Kopf habe und ich hier und da noch mal nachschlagen muss. Aber du solltest das alles zumindest schon mal gehört und auch verstanden haben. Man kann sich natürlich C auch beim µC Programmieren beibringen. Einfacher geht es aber erstmal die Sprache auf einem normalen Computer zu lernen, auf dem man dann auch die Standardausgabe printf usw. einfach benutzen kann, einfache Möglichkeiten zum Debuggen hat und sich auch keine Gedanken über Speicher und Performance machen muss. Ein aktuelles Notebook/PC hat davon einfach genug (zumindest für das was wir jetzt machen wollen). Ich persönlich benutze zum Testen von Programmschnipseln und Algorithmen gerne den Onlineservice von https://www.tutorialspoint.com/compile_c_online.php dort kann man einfach loslegen und der verwendete GCC Compiler ist dem AVR-GCC auch ziemlich ähnlich. Wenn du mit C soweit vertraut bist, solltest du mit dem bereits verlinkten AVR-Tutorial weitermachen. Dann sollte mit den bereits gegebenen Tipps der Rest relativ einfach sein. Frohes Schaffen, Bimbo385
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.