Hallo zusammen,
Ich möchte bei einem Projekt ein eingehendes PWM-Signal auslesen, dazu
stehen mir aber leider wegen unüberlegter PIN-Belegung die PWMI-Timer
Register des STM8 nicht zur Verfügung. Dementsprechend wollte ich
einfach die Zeit, die zwischen zwei Taktflanken vergeht auslesen und
"berechnen". Zum Test habe ich einen Pulsgenerator mit einem bestimmten
PWM-Signal angelegt und mir im Debug-Modus die Variablen (natürlich
nachdem die Zeit gemessen war) angeschaut.
Nun ist folgendes Problem aufgetaucht und zwar wird bei einem duty-cycle
>50% die Berechnung wohl eher ein Random-Number-Generator, dieses
Problem tritt bei einem duty-cycle von ca 30% auch jeden 3.Aufruf auf.
Woran liegt das, dass der Interrupt einfach mal zu früh triggert? Bricht
die Spannung am Pulsgenerator vielleicht alle paar Flanken mal ein
(Kann ich das ein einem Oszi überprüfen?)? Oder liegt es am Programm?
GIbt es hierfür vielleicht ein "bekanntes" workaround, sodass wenigstens
die Werte annähernd genau sind?
Hier noch das Programm:
main:
1 | main()
|
2 | {
|
3 | _asm("sim");
|
4 | CLK_CONF();
|
5 | GPIO_CONF();
|
6 | TIM2_CONF();
|
7 | TIM4_CONF();
|
8 | _asm ("rim");
|
9 | while(1);
|
Tim4 ISR & Conf:
1 | void TIM4_CONF(void){
|
2 | TIM4->PSCR |= 0x02;
|
3 | TIM4->CNTR = 0xFA;
|
4 | TIM4->IER |= 0x01;
|
5 | TIM4->CR1 = 0x01;
|
6 | }
|
7 | @far @interrupt void TIM4_UPD_OVF_IRQHandler(void)
|
8 | {
|
9 | /*GPIOD->ODR ^= ((1<<3)|(1<<4));
|
10 | GPIOA->ODR ^= 1<<3;*/
|
11 | if(FbFlag){
|
12 | ovFlag++;
|
13 | }else{
|
14 | ovFlag = 0;
|
15 | }
|
16 | TIM4->SR1 = ~0x01; //Clear Flag
|
17 | }
|
PortC-Interrupt (so konfiguriert, dass EXTI auf rising und falling
triggert):
1 | @far @interrupt void EXTI_PORTC_IRQHandler(void)
|
2 | {
|
3 | if((GPIOC->IDR & 1<<6) == (1<<6)){
|
4 | if(FlankFlag == 0){
|
5 | FbFlag = TRUE;
|
6 | T1_H = TIM4->CNTR;
|
7 | FlankFlag++;
|
8 | }else if(FlankFlag == 2){
|
9 | T2_H = ((TIM4->CNTR)+250*ovFlag);
|
10 | Period = T2_H-T1_H;
|
11 | T1_L = T1_L/100;
|
12 | T2_H = T2_H/100;
|
13 | FbFlag = FALSE;
|
14 | FlankFlag = 0;
|
15 | DutyCycle = (float)((T1_L*100)/T2_H);
|
16 | ovFlag = 0;
|
17 | }
|
18 | }else if((GPIOC->IDR & 1<<6) == 0){
|
19 | if(FlankFlag == 1){
|
20 | T1_L = ((TIM4->CNTR)+250*ovFlag);
|
21 | T1_L_OVF = ovFlag;
|
22 | FlankFlag++;
|
23 | }
|
24 | }
|
25 |
|
26 | }
|