Hi all
I am a self taught tinkerer/newbie and am working on a small project that is using a PIC12F1571 (I may switch to a PIC12F1572 if I run out of code space) as the controller in an infra-red key fob transmitter.
Due to space constraints I have to keep the physical size of the chip and associated circuitry as small as possible (yet still be able to hand solder the PCB), because of this I am trying to use one ADC pin for all 5 switches, I only ever need to be able to read one switch at a time and so I have set up a simple resister chain - see schematic. When checked with a DMM I can see that the ADC pin is receiving the input that I expect it to but I cannot get it to reliably read the ADC input if at all. (Please note that my test circuit [V1 - built on stripboard] has the switches wired to VDD and R3 to VSS - the configuration has been swapped in the V2 design to allow better low voltage reliability).
My programming environment is MPLAB X V3.15 and XC8 V1.35 with a PICKit 3 as the programmer/debuger.
Here is my code - I have been over it and the data sheet several times but can't see what is wrong - I am sure that it is probably staring me in the face but need your help to see it.
configuration_bits.c
if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#endif
// PIC12F1571 Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG1
#pragma config FOSC = INTOSC // (INTOSC oscillator; I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL Disabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOREN = OFF // Low Power Brown-out Reset enable bit (LPBOR is disabled)
#pragma config LVP = OFF // Low-Voltage Programming Disable (Low-voltage programming Disabled)
system.h
#define SYS_FREQ 250000L
#define FCY SYS_FREQ/4
void ConfigureOscillator(void); /* Handles clock switching/osc initialization */
user.h
/******************************************************************************/
/* User Level #define Macros */
/******************************************************************************/
#define Umpire_Box
//#define Medic_Box
/* TODO Application specific user parameters used in user.c may go here */
#define VisLED_Port LATAbits.LATA2 //Location of the Indicator LED
#define VisLED_Tris TRISAbits.TRISA2
#define VisLED_Off 0
#define VisLED_On 1
#define IRLED_Port LATAbits.LATA5 //Location Of the IR LED
#define IRLED_Tris TRISAbits.TRISA5
#define IRLED_Drive ODCONAbits.ODA5
#define IRLED_Off 1
#define IRLED_On 0
#define PWR_SW_Port LATAbits.LATA1 //Location Of The Power Mosfet
#define PWR_SW_Tris TRISAbits.TRISA1
#define PWR_SW_Drive ODCONAbits.ODA1
#define OP_SW_Tris TRISAbits.TRISA4 //Location of the input switches
#define OP_SW_Port ANSELAbits.ANSA4
#define OP_SW_CHS 0b00011
#define PWR_On 0
#define PWR_Off 1
#define _XTAL_FREQ 250000 //This is the speed your controller is running at
void InitApp(void); /* I/O and Peripheral Initialization */
void Setup_Switch_Read(void);
void Read_Switch_Input(void);
void half_second_delay(void);
system.c
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#endif
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include "system.h"
void ConfigureOscillator(void)
{
OSCCONbits.IRCF = 0b0110; //250KHz Oscillator
OSCCONbits.SPLLEN = 0; //4X PLL Disabled
}
main.c
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#endif
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include "system.h" /* System funct/params, like osc/peripheral config */
#include "user.h" /* User funct/params, such as InitApp */
int Switch;
void main(void)
{
/* Configure the oscillator for the device */
ConfigureOscillator();
/* Initialize I/O and Peripherals for application */
InitApp();
PWR_SW_Port = PWR_On;
__delay_ms(1);
Setup_Switch_Read();
//VisLED_Port = VisLED_On;
while(1)
{
Read_Switch_Input();
#ifdef Umpire_Box
{
if (Switch == 1)
{
Set_PWM3_Duty_Cycle(0x2000);
}
else if (Switch == 2)
{
Set_PWM3_Duty_Cycle(0x4000);
}
else if (Switch == 3)
{
Set_PWM3_Duty_Cycle(0x6000);
}
else if (Switch == 4)
{
Set_PWM3_Duty_Cycle(0xC000);
}
else if (Switch == 5)
{
Set_PWM3_Duty_Cycle(0xF000);
}
else
{
Set_PWM3_Duty_Cycle(0x8000);
}
}
#endif
#ifdef Medic_Box
#endif
__delay_ms(1000);
// Set_PWM3_Duty_Cycle(PWM3DC + 1000);
}
// PWR_SW_Port = PWR_Off;
}
void Read_Switch_Input(void)
{
PIR1bits.ADIF = 0; //Clear ADC Interrupt Flag
ADCON0bits.GO_nDONE = 1; //Start ADC Conversion
while(ADCON0bits.GO_nDONE == 1) //Wait for ADC Conversion to be complete
{
//wait for result
}
if (ADRESL > 224)
{
Switch = 1;
}
else if (ADRESL > 173)
{
Switch = 2;
}
else if (ADRESL > 141)
{
Switch = 3;
}
else if (ADRESL > 122)
{
Switch = 4;
}
else if (ADRESL > 96)
{
Switch = 5;
}
else
{
Switch = 0;
}
}
user.c
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#endif
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include "user.h"
void InitApp(void)
{
/* TODO Initialize User Ports/Peripherals/Project here */
APFCONbits.P1SEL = 1; //Set PWM1 to RA5
CM1CON0bits.C1ON = 0; //disable compareter module.
ODCONA = 0x00; //Set Port A pins to drive and sink current
IRLED_Drive = 1; //Set pin as current sink only
PWR_SW_Drive = 1; //Set pin as current sink only
PWR_SW_Tris = 0; //Set as Output
VisLED_Tris = 0; //Set as Output
IRLED_Tris = 0; //Set as Output
Setup_PWM3();
Set_PWM3_Period(0xFFFF);
Set_PWM3_Duty_Cycle(0x8000);
Start_PWM3();
/* Setup analog functionality and port direction */
/* Initialize peripherals */
/* Enable interrupts */
}
void Setup_Switch_Read(void)
{
ADCON0bits.ADON = 1; //Enable ADC Module
OP_SW_Tris = 1; //Set Input switch port as input
OP_SW_Port = 1; //Set Pin as analog input
ADCON0bits.CHS = OP_SW_CHS; //Select Channel for measurement
//ADC TAD Clock period should fall between 1.0 and 6.0 uS
//Fosc = 250KHz
//ADCS 0b000 = Fosc/2 which is a period of 8us <- Too long
//Therefore ADCS must be set to FRC = 0b111 or 0b011
ADCON1bits.ADCS = 0b111; //Set ADC Conversion clock to FRC
ADCON1bits.ADPREF = 0b00; //Set ADC voltage reference to VDD
ADCON1bits.ADFM = 0; //Set ADC result to right justified
ADCON2bits.TRIGSEL = 0x0; //Auto conversion Trigger disabled
__delay_ms(5); //Allow the module to settle
}
Any help that you can give will be much appreciated.
Thank you
Jem