Danke für eure Antworten, aber anscheinend ist die Syntax etwas anders
(danke an hp-freund für den Hinweis mal in den Header-Dateien
nachzuschauen). So compiliert es zumindest:
1
voidinitADC(){
2
ADC1->CR1|=ADC1_CR1_ADON;//turn ADC on
3
ADC1->CSR|=(1<<3);//Pin D3 (AIN4) as Analog Channel
4
ADC1->CR1|=(1<<2);//Set Prescaler to f/4 of master (4MHz)
google schrieb:> muss das nicht ADC_CR1->CH heißen?
Nein, Deine Bezeichnung war richtig. Aber CH[0..3] sind vier Bits, in C
ein Bitfeld. Guck in die zugehörige .h Datei, wie vorher schon
geschrieben. Dort steht, wie Du es in Assembler ansprechen kannst. (Von
Assembler hab ich keine Ahnung)
google schrieb:> Aber CH[0..3] sind vier Bits, in C> ein Bitfeld.
Soweit ich die Beschreibung des Registers richtig verstehe:
Bits 3:0 CH[3:0]: Channel selection bits
These bits are set and cleared by software. They select the input
channel to be converted.
0000: Channel AIN0
0001: Channel AIN1
....
1111: Channel AIN15
müsste ich für "AIN4" 0100 schreiben, dann müsste (1<<3) doch stimmen,
oder?
google schrieb:> Vielleicht hilft Dir das etwas, er erklärt alles immer recht gut.
Danke für den Link, aber da ist die Syntax auch anders als in STVD
(warum eigentlich keine einheitliche Syntax?).
Edit: Noch eine Frage, warum bekomme ich hier den Fehler "missing
prototype" (bei "initADC();")? Ich hab doch mit
1
uint16_treadAnalogValue();
die Methode ganz brav "vorinitialisiert"?
1
#include<stm8s.h>
2
3
voidinitADC();
4
voidinitADC(){
5
ADC1->CR1|=ADC1_CR1_ADON;//turn ADC on
6
ADC1->CSR|=(1<<3);//Pin D3 (AIN4) as Analog Channel
7
ADC1->CR1|=(1<<2);//Set Prescaler to f/4 of master (4MHz)
8
}
9
10
uint16_treadAnalogValue();
11
uint16_treadAnalogValue(){
12
if((ADC1->CSR&(1<<7))==1){//check End of Conversion Bit
google schrieb:> Dort steht, wie Du es in Assembler ansprechen kannst. (Von> Assembler hab ich keine Ahnung)
Ich hab im Titel "ST Visual Develop" gelesen und das unmittelbar mit
Assembler assoziiert, sorry. Du bist ja in C unterwegs. Welchen Compiler
nutzt Du?
Laß mal die "Prototypen" vorläufig weg:
> void initADC();> uint16_t readAnalogValue();> void delay_ms(uint16_t ms);
Wie es richtig geht und warum man die braucht, steht hier:
http://www.c-howto.de/tutorial-funktionen-funktions-prototypen.html
google schrieb:> Du bist ja in C unterwegs. Welchen Compiler> nutzt Du?
Jup, ich nutze den Cosmic C compiler. Den gibts ja seit März '16
kostenlos ohne Codebeschränkung!
google schrieb:> Laß mal die "Prototypen" vorläufig weg:
Anscheinend ist da mein Compiler (?) ziemlich pingelig, so
funktionierts:
1
uint16_treadAnalogValue(void);
2
uint16_treadAnalogValue(){
3
if((ADC1->CSR&(1<<7))==1){//check End of Conversion Bit
4
uint8_thRegister=ADC1->DRH;
5
uint8_tlRegister=ADC1->DRL;
6
7
uint16_tcompleteValue=hRegister<<8|lRegister;
8
returncompleteValue;
9
}
10
}
Anscheinend fehlt noch irgendwas bei der Initialisierung da:
Hm, bin leider immer noch nicht weiter gekommen, das hier ist mein Code:
1
/* MAIN.C file */
2
#include<stm8s.h>
3
4
voidinitADC(void);
5
voidinitADC(){
6
ADC1->CR1|=(1<<0);//turn ADC on
7
ADC1->CSR|=(1<<2);//Pin D3 (AIN4) as Analog Channel
8
ADC1->CR1|=(1<<5);//Set Prescaler to f/4 of master (4MHz)
9
}
10
11
uint16_treadAnalogValue(void);
12
uint16_treadAnalogValue(){
13
ADC1->CSR&=~(1<<7);
14
ADC1->CR1|=(1<<0);//Start conversion
15
if((ADC1->CSR&(1<<7))==1){//check End of Conversion Bit
16
uint8_thRegister=ADC1->DRH;
17
uint8_tlRegister=ADC1->DRL;
18
19
uint16_tcompleteValue=hRegister<<8|lRegister;
20
returncompleteValue;
21
}
22
}
23
24
voiddelay_ms(uint16_tms);
25
voiddelay_ms(uint16_tms){
26
while(ms--){
27
uint16_ti;
28
for(i=0;i<ms;i++){
29
nop();
30
}
31
}
32
}
33
34
voidmain()
35
{
36
GPIOC->DDR|=(1<<7);//PD3 as Output
37
GPIOC->CR1|=(1<<7);//PD3 as Push Pull
38
39
initADC();
40
while(1){
41
uint16_tadc_value=readAnalogValue();
42
if(adc_value>0){
43
GPIOC->ODR|=(1<<7);//turn PD3 on
44
delay_ms(250);
45
GPIOC->ODR&=~(1<<7);//turn PD3 off
46
delay_ms(250);
47
}
48
}
49
}
Beim Debuggen ist der Wert der "adc_value" Variable zu Beginn "256",
danach aber immer 0.Laut Datenblatt muss ich das erste Bit im CR1
Register sowohl setzen, um den ADC aufzuwecken als auch um eine
Umrechnung zu starten. Beides mache ich ja. Wo liegt nun mein Fehler?
Max M. schrieb:> Beim Debuggen ist der Wert der "adc_value" Variable zu Beginn "256",> danach aber immer 0.Laut Datenblatt muss ich das erste Bit im CR1> Register sowohl setzen, um den ADC aufzuwecken als auch um eine> Umrechnung zu starten. Beides mache ich ja. Wo liegt nun mein Fehler?
Es gibt zich Beispiele. Guck Sie dir an. Debugge erstmal die Register
durch sind diese auch richtig gesetzt? Vielleicht hast du irgendeine
clock nicht gesetzt.
mfg
aSma>> schrieb:> Man hat dir schon ein Link> geschickt wie man richtig Prototypen deklariert.
Achso, die Reihenfolge des Codes ändert natürlich alles. Das dient
bestenfalls der Übersichtlichkeit, ändert aber, in meinem Beispiel,
nichts an der Funktionalität.
aSma>> schrieb:> Es gibt zich Beispiele. Guck Sie dir an.
Wenn es wirklich so viele gäbe, hätte ich nicht gefragt.
Aber, danke für die Antwort.
ADC1->CSR|=(1<<2);//Pin D3 (AIN4) as Analog Channel
11
ADC1->CR1|=(1<<5);//Set Prescaler to f/4 of master (4MHz)
12
}
13
14
uint16_treadAnalogValue(){
15
ADC1->CSR&=~(1<<7);//reset End of Conversion Bit
16
ADC1->CR1|=(1<<0);//Start conversion
17
delay_ms(10);
18
if((ADC1->CSR&(1<<7))){//check End of Conversion Bit
19
uint8_thRegister=ADC1->DRH;
20
uint8_tlRegister=ADC1->DRL;
21
22
uint16_tcompleteValue=hRegister<<8|lRegister;
23
returncompleteValue;
24
}
25
}
26
27
voiddelay_ms(uint16_tms){
28
while(ms--){
29
uint16_ti;
30
for(i=0;i<ms;i++){
31
nop();
32
}
33
}
34
}
35
36
voidmain()
37
{
38
GPIOC->DDR|=(1<<7);//PD3 as Output
39
GPIOC->CR1|=(1<<7);//PD3 as Push Pull
40
41
initADC();
42
while(1){
43
uint16_tadc_value=readAnalogValue();
44
45
if(adc_value>20){
46
GPIOC->ODR|=(1<<7);//turn PD3 on
47
delay_ms(250);
48
GPIOC->ODR&=~(1<<7);//turn PD3 off
49
delay_ms(250);
50
}
51
}
52
}
Beim Debuggen werden Werte um die ~3100 angezeigt. Jetzt ist nur die
Frage, wie ich diesen Wert wieder in die Eingangsspannung umwandel? In
den Dokumenten finde ich keine Formel, wie der ADC-Wert berechnet wird,
oder hab ich was übersehen?
Max M. schrieb:> Danke, das kommt hin! Aber woher hattest du diese Formel? Oder aus> welchen Gegebenheiten erschließt sich die?
Servus,
einfacher Dreisatz Kollega.
Wobei ich der stm8 eher 10bit ADC hat. K.A. steht alles in den
Datenblätter.
Eine analoge Spannung wird immer durch einen ADC digitalisiert, d.h. es
werden diskrete Werte von den gemessenen analogen Wert aufgenommen.
Annahme 10bit Auflösung: 2^10-1 ergibt 1023. stm8 hat 5 Volt ADC
Eingänge.
Klingelt es ?
mfg
aSma>> schrieb:> Wobei ich der stm8 eher 10bit ADC hat. K.A. steht alles in den> Datenblätter.
Korrekt. Wobei ich jetzt einfach von left aligned ausgegangen bin, weil
er einen Wert >1023 rausbekommen hat :)
ST stellt für den STM8 eine Lib bereit.
Sieht dann so aus und der Käse ist gegessen:
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_6,
ADC1_PRESSEL_FCPU_D18, ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT,
ADC1_SCHMITTTRIG_CHANNEL0, DISABLE);
aSma>> schrieb:> Annahme 10bit Auflösung: 2^10-1 ergibt 1023. stm8 hat 5 Volt ADC> Eingänge.> Klingelt es ?
Ehrlich gesagt nicht. Beim Atmega des Arduino war die Formel für mich
eingängiger, da die Auflösung, wie du schon sagst, 2^10 beträgt. Von
daher wäre Vref / 1024 (wie es bei den Atmegas auch ist) sinnvoller. Wie
man auf 2^16 kommt, ist mir nicht klar.
Eric B. schrieb:> Nein. 0100 wäre (1<<2), oder einfach 4.
Danke.
honk schrieb:> Sieht dann so aus und der Käse ist gegessen:
Das sieht jetzt aber auch nicht wesentlich kürzer aus im Vergleich zu
meiner Init-Funktion.
Max M. schrieb:> Ehrlich gesagt nicht. Beim Atmega des Arduino war die Formel für mich> eingängiger, da die Auflösung, wie du schon sagst, 2^10 beträgt. Von> daher wäre Vref / 1024 (wie es bei den Atmegas auch ist) sinnvoller. Wie> man auf 2^16 kommt, ist mir nicht klar.
Aber nur wenn das entsprechende Config-Bit 0 ist. Wenn es 1 ist muß man
auch beim ATmega mit 2^16 rechnen (oder mit 2^8, je nachdem wie man den
ADC Wert ausliest).