Givetvis går det inte som planerat - inget händer.
Det bästa tipset jag fått när det gäller att felsöka i koden är att bryta ner i delar, och se till att varje enskild funktion fungerar som tänkt. Satt flertalet timmar och försökte göra det men jag tror inte jag är skapt för att programmera, det blir bara rörigare. Jag rörde till i koden så vida pass att jag fick återgå till originalprogrammet igen.
I förhoppning att slutföra det här, eller i alla fall känna att jag är "på väg", finns det någon vänlig själ som kan hjälpa mig på traven? Gissningsvis så blir det svårt i och med ett (i mina ögon) stort program och väldigt PIC-specifikt. Blir riktigt besviken på mig själv att så många projekt bara ligger pga oklar kod.
Kod: Markera allt
/************************************************************
* HEADLAMP *
* *
* MCU: PIC12F1840 *
* S/W version: 0.1 *
* Creator: Magnus *
* *
* I/O: PORT PIN No Function *
* RA0 7 Buzzer *
* RA1 6 Indicator LED, RED *
* RA2 5 LED output *
* RA3 4 Pushbutton *
* RA4 3 Batt voltage (ADC AN3) *
* RA5 2 Indicator LED, GREEN *
* VDD 1 Batt power *
* VSS 8 GND *
* *
* TODO: CLOCK *
* Internal OSC 8 Mhz.......................OK! *
* I/Os *
* RA0, RA1, R2, RA5 outputs................OK! *
* RA3, RA4 inputs..........................OK! *
* TYPE *
* RA3 Digital, RA4 Analog................OK! *
* PWM (1 kHz).................................. *
* TIMER x 3 *
* Timer0 = Basic timer.......................OK! *
* Timer1 = SoftPWM timer for buzzer..........OK! *
* Timer2 = Timer dedicated to PWM-module.....OK! *
* ADC.......................................... *
* *
* ONGOING: *
* *
************************************************************/
#include <stdint.h>
#define BUTTON_R PORTA.B3
#define BUTTON_W LATA.B3
#define G_LED_R PORTA.B5
#define G_LED_W LATA.B5
#define R_LED_R PORTA.B1
#define R_LED_W LATA.B1
#define BUZZER_R PORTA.B0
#define BUZZER_W LATA.B0
void init(){
// Setup of oscillator clock. 8MHz to be used as Fosc
OSCCON = 0b01110010;
// Setup of I/O:s
PORTA = 0;
TRISA = 0b00011000;
ANSELA = 0b00010000; // Turn on Analog SELect for RA4
ADCON0 = 0b00001111;
ADCON1 = 0b00100011;
// Setup of internal voltage reference, 2.048V will be used
FVRCON = 0b10000010;
// Setup of interrupts
INTCON.GIE = 1;
INTCON.PEIE = 1;
INTCON.TMR0IE = 1;
PIR1 = 0; // Clear all interrupt flags
PIE1.TMR1IE = 0;
T1CON = 0x01; // Enable T1
INTCON.IOCIE = 1;
IOCAN.IOCAN0 = 1;
// Setup of basic timer to be used with debounce and counter, rollover at 9,9ms
OPTION_REG = 0b00000110; // 1/128 Prescaler
TMR0 = 100; // Pre-set value
// Setup of basic timer to be used with buzzer, frequency at 1,5kHz
TMR1H = 0xFC;
TMR1L = 0x18;
// Setup of PWM
CCP1CON = 0b00111100 ; // ..00.... Use 8 bit res, 11 = use the two LSB's
// ....1100 P1A Active High, P1B Active High
PR2 = 0xFF; // PWM period (100)
CCPR1L = 0xFF;
T2CON = 0b00000111; // T2 on with prescaler set to 64
}
uint8_t buttonStatus;
uint8_t pushRegistered;
uint8_t buzzdurationCounter;
uint16_t battcheckCounter;
enum processorStates {
ERROR,
RUNNING,
GOTO_SLEEP,
RECOVER
};
enum lampFunctions {
OFF,
LED_HIGH,
LED_LOW
};
enum buzzLengths {
SHORT,
LONG
};
enum processorStates processorState = GOTO_SLEEP;
enum lampFunctions lampFunction = OFF;
enum buzzLengths buzzLength = SHORT;
/***********************************************************************/
void setSleep(){
TRISA = 0b00111111; // Set all I/O:s to inputs
FVRCON.FVREN = 0; // Turn off Voltage reference
VREGCON = 0x03; // Use low power sleep
if(!buttonStatus){ // Only put to sleep when button has been released
processorState = RECOVER;
asm sleep;
}
}
/***********************************************************************/
uint8_t get_voltage(){
uint8_t voltage_level = 0;
if(FVRCON.FVRRDY){
voltage_level = ADRESH;
ADCON0.GO = 1;
} else {
processorState = ERROR;
}
return voltage_level;
}
/***********************************************************************/
void recover_from_sleep(){
uint8_t startupVoltage = 0;
TRISA = 0b00011000; // Restore all I/O:s
IOCAF.IOCAF3 = 0; // Reset the IOC flag bit
FVRCON.FVREN = 1; // Enable Internal Voltage reference
while(!FVRCON.FVRRDY){}
startupVoltage = get_voltage();
if(startupVoltage >= 190) {
processorState = RUNNING;
} else {
processorState = ERROR;
}
}
/***********************************************************************/
void do_buzz(enum buzzLengths buzzLength){
switch(buzzlength){
case SHORT:
PIR1.TMR1IE = 1;
buzzdurationCounter = 60; // Minimum 50 as base value
break;
case LONG:
PIR1.TMR1IE = 1;
buzzdurationCounter = 90; // Minimum 50 as base value
break;
default:
processorState = ERROR;
break;
}
}
/***********************************************************************/
void battcheck(){
uint8_t batt_level = 0;
batt_level = get_voltage();
// Check voltage each 2 minute. Decrease interval av make a buzz below 3,6V
// (225 ADC value). Turn of LED and put lamp in ERROR state below 3V (187 ADC value))
if(batt_level >= 226) {
battcheckCounter = 0; // New battcheck every 2 min
}
else if((batt_level <= 225) && (batt_level >= 200)) {
do_buzz(SHORT);
battcheckCounter = 6000; // New battcheck and buzz every minute
}
else if((batt_level <= 199) && (batt_level >= 189)) {
do_buzz(SHORT);
battcheckCounter = 9000; // New battcheck and buzz every 30 sec
}
else if((batt_level <= 188) && (batt_level >= 187)) {
do_buzz(LONG);
battcheckCounter = 11900; // New battcheck and buzz every sec
}
else if(batt_level <= 186) {
processorState = ERROR;
}
}
/***********************************************************************/
void steady(){
if(buttonStatus && (!pushRegistered)){ // When button has been debounced
pushRegistered = 1; // and not been registered yet then
// do the following.
lampFunction = (lampFunction + 1);
if(lampFunction >= 3){
lampFunction = 0;
}
}
switch(lampFunction) {
case OFF:
processorState = GOTO_SLEEP;
break;
case LED_HIGH:
CCPR1L = 0xFF; // PWM at 100% DC
if(12000 <= battcheckCounter) { // 12000 = 10ms x 2 min
battcheck();
}
break;
case LED_LOW:
CCPR1L = 0x7F; // PWM at 50% DC
if(12000 <= battcheckCounter) { // 12000 = 10ms x 2 min
battcheck();
}
default:
processorState = ERROR;
break;
}
}
/***********************************************************************/
void warning(){
R_LED_W = 1;
}
/***********************************************************************/
void interrupt(){
if(INTCON.TMR0IF) { // This interrupt occurs each 10ms
// and is only turned off in sleep
static uint8_t debounceCounter;
battcheckCounter++;
INTCON.TMR0IF= 0; // Reset interruptflag
TMR0 = 100; // Pre-set timer value
debounceCounter <<= 1;
debounceCounter |= BUTTON_R;
if (debounceCounter == 0x00) { // Om byte:n endast innehåller 0:or
buttonStatus = 1; // så sätt status till 1
}
else if (debounceCounter == 0xFF) { // Om byte:n endast innehåller 1:or
buttonStatus = 0; // så sätt status till 0
pushRegistered = 0;
}
if(PIR1.TMR1IE){
buzzdurationCounter--;
if(50 >= buzzdurationCounter){
PIR1.TMR1IE = 0;
}
}
}
if(PIR1.TMR1IF) { // If enabled, this interrupt occurs
// with a freq of 2kHz
PIR1.TMR1IF = 0;
TMR1H = 0xFC;
TMR1L = 0x18;
BUZZER_W &= ~BUZZER_W;
}
}
/***********************************************************************/
void main(void) {
init();
while(1){
switch(processorState) {
case ERROR:
warning();
break;
case RUNNING:
steady();
break;
case GOTO_SLEEP:
setSleep();
break;
case RECOVER:
recover_from_sleep();
break;
default:
warning();
break;
}
}
}