Problemet är att jag inte kan läsa av knappen S1. En utförligare beskrivning av problemet kommer längre ner.
Så här ser schemat ut:

Kort beskrivning av kretsen:
Klockkretsen DS1307 generar avbrott 2 ggr/s genom att toggla ben 7 SQW/OUT.
Togglingen aktiverar ett "Pin Change Interrrupt" i MCUn.
Drivaren på SQW/OUT är av typen öppen kollektor så MCUns interna pullup är aktiverad på pinne PC3 för att undvika att pinnen flyter.
Detta gäller även för PD3 dit tryckknappen S1 är kopplad.
MCUn använder intern oscillator inställd på 8MHz.
PB0, PB1, PB2 och PD7 används för att styra H-bryggan.
I dagsläget är inget kopplat till H-bryggans utgångar.
Programmet:
Mjukvaran initierar PortB, PortD, timer0 och Pin change interrupt.
Varje gång det kommer ett interrupt på PC3 avläses värdet på PD3.
Beroende på värdet på PD3 sätts en global variabel (boButtonState) till antingen 0 eller 1.
I main finns en evighets-loop som kollar värdet på boButtonState.
Om boButtonState = 1 aktiveras två transistorer i H-bryggan. Efter 100 ms stängs alla transistorerna av och programmet väntar i 100 ms till innan loopen börjar om.
Om boButtonState = 0 görs ingenting och loopen börjar om.
Detta borde således resultera i en pulserande spänning ut från H-bryggan som är hög i 100ms och låg i 100ms.
Beskrivning av problemet:
Problemet är att det inte blir någon snygg pulserande spänning ut från H-bryggan då knappen trycks ner.
Det som händer är att så länge som boButtonState = 1 lägger MCUn ut en fyrkantsspänning på PB1 och PD7 med en periodtid på 2*900us istället för 2*100ms som det borde vara.
När boButtonState återgår till 0 så sätts PB0, PB1, PB2 och PD7 till 0V.
Jag har även provat att invertera avläsningen av knappen så att H-bryggan aktiveras då knappen är uppsläppt. Detta resulterade i att samma snabba fyrkantspänning kunde observeras då knappen var uppsläppt.
Har också provat att kommentera bort if-satsen som läser boButtonState och då blir det fina 100 ms pulser ut.
Först misstänkte jag någon form av EMC-problem, men anser att det kan avfärdas eftersom det funkar fint då man inte läser av knappen. Har kollat matningsspänning med oscilloskop och inte hittat något anmärkningsvärt.
Jag har kapat bort så mycket som möjligt av koden för att isolera problemet men nu har ideerna tagit slut. Är mycket tacksam om någon har några föslag på vad det kan vara eller var jag kan fortsätta letandet.
/John
Bifogar koden
Kompilerat med avr gcc utan någon optimering
Kod: Markera allt
#include <avr\io.h>
#include <avr\interrupt.h>
#include <avr\eeprom.h>
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
typedef unsigned long long u64;
typedef signed char s8;
typedef signed int s16;
typedef signed long s32;
typedef signed long long s64;
/* structs */
typedef struct
{
u8 u8TCCRxA;
u8 u8TCCRxB;
u16 u16TCNTx;
u16 u16OCRxA;
u16 u16OCRxB;
u8 u8TIMSKx;
u8 u8TIFRx;
u8 u8ASSR; /* Only used by timer2 */
u8 u8GTCCR; /* Only used by timer2 */
}timerRegStruct;
/* Prototypes */
void initInterrupts();
void initPorts();
void initTimer0(timerRegStruct *timerRegPtr);
void initTimer1(timerRegStruct *timerRegPtr);
void initTimer2(timerRegStruct *timerRegPtr);
void wait(u16 u16delayMs);
void setPositive();
void setNegative();
void setNone();
/* Pinning aliases */
#define HI_A (7)
#define LO_A (0)
#define HI_B (2)
#define LO_B (1)
#define BUTTON (3)
/* Macros */
#define setBit(port, bit) \
asm("sbi %0, %1" :: "I" (_SFR_IO_ADDR(port)), "I"(bit) )
#define clearBit(port, bit) \
asm("cbi %0, %1" :: "I" (_SFR_IO_ADDR(port)), "I"(bit) )
/* Global variables */
static u8 boButtonState = 0;
static u8 boManageClockFlag = 0;
/****************************************************************************************
* Interrupt service routine
****************************************************************************************
*/
ISR(PCINT1_vect)
{
u8 u8PinD = PIND;
boManageClockFlag = 1;
if (u8PinD & (1<< BUTTON))
{
boButtonState = 0;
}
else
{
boButtonState = 1;
}
}
/****************************************************************************************
* Main
****************************************************************************************
*/
int main()
{
/* Timer settings */
static const timerRegStruct timer0Str =
{
0, /* Normal operation */
0, /* Timer0 OFF */
0, /* Counter register */
255, /* Output compare register A */
255, /* Output compare register B */
0, /* Interrupt register */
0, /* Interrupt flag register */
0, /* ASSR not used by Timer0 */
0 /* GTCCR not used by Timer0 */
};
/* Make sure interrupts are disabled */
cli();
/* Init HW modules */
initTimer0(&timer0Str);
initPorts();
ACSR = 0; /* Disable Analog Comparator */
wait(500);
initInterrupts();
while (1)
{
if (boButtonState)
{
setPositive();
wait(100);
setNone();
wait(100);
boManageClockFlag = 0;
}
}
}
/*
* wait function uses Timer0 to wait the specified time in milliseconds.
* Returns when specified time has elapsed
*/
void wait(u16 u16DelayMs)
{
u16 u16i;
/* repeat for the number of milliseconds */
for (u16i = 0; u16i < u16DelayMs; u16i++)
{
TCCR0A = 0;
TCNT0 = 0;
OCR0A = 124; /* 125 * 64 = 8000 => Timer0 period = 1 ms @ 8 MHz*/
OCR0B = 255;
TIMSK0 = 0;
TIFR0 = (1 << OCF0A);
TCCR0B = 3; /* Timer0 prescaler = 64 */
while (!(TIFR0 && (1 << OCF0A)))
{
/* Wait for Timer0 to elapse */
}
}
}
/*
* Activates forward current
*/
void setPositive()
{
clearBit(PORTB,HI_B);
clearBit(PORTB,LO_A);
setBit(PORTB,LO_B);
setBit(PORTD,HI_A);
}
/*
* Activates reverse current
*/
void setNegative()
{
clearBit(PORTD,HI_A);
clearBit(PORTB,LO_B);
setBit(PORTB,LO_A);
setBit(PORTB,HI_B);
}
/*
* Deactivates H-bridge
*/
void setNone()
{
clearBit(PORTB,LO_A);
clearBit(PORTB,HI_B);
clearBit(PORTB,LO_B);
clearBit(PORTD,HI_A);
}
void initInterrupts()
{
/* Make sure that INT0 and INT1 are disabled */
EIMSK = 0;
/* Clear interrupt flag register */
PCIFR = (1<<PCIF2) | (1<<PCIF1) | (1<<PCIF0);
/* Activate pin change interrupt on PC3 */
PCMSK0 = 0;
PCMSK1 = (1<<PCINT11);
PCMSK2 = 0;
PCICR = (1<<PCIE1);
/* Enable global interrupts */
sei();
}
void initTimer0(timerRegStruct *timerRegPtr)
{
TCCR0A = timerRegPtr->u8TCCRxA;
TCNT0 = (u8) (timerRegPtr->u16TCNTx);
OCR0A = (u8) (timerRegPtr->u16OCRxA);
OCR0B = (u8) (timerRegPtr->u16OCRxB);
TIMSK0 = timerRegPtr->u8TIMSKx;
TIFR0 = timerRegPtr->u8TIFRx;
TCCR0B = timerRegPtr->u8TCCRxB;
}
void initPorts()
{
PORTC = 0x08; /*Activate pullup on SQW pin */
PORTB = 0;
PORTD = 0x08; /* Activate pullup on button PD3 */
/* H-bridge driver pins to outputs */
DDRB = (1<<LO_A) | (1<<LO_B) | (1<<HI_B);
DDRD = (1<<HI_A);
}