the first change to make is to the ADC capture method.
use ADC_INIT(); to setup the ADC
and then call the ADC by using the function ADC_get_sample(0);
replacing adc_read(0); with ADC_Get_Sample(0); will speed up the adc routine.
read the help file for full details.
The next thing to do is to look into using interrupt to run the 7seg refresh rate. i have built the attached code to show how to update the 7seg using an ISR. The code is documented so reading through it should be enough to grasp the concept. This code should run on Easypic 4, 5, 7
you will note that i have fixed the ADC value as if it had been 10, this would result in the 7seg showing 10*352 = [MSB]3520[LSB]
Code: Select all
//******************************************************************************
//
// PIC16F887
//
// 8MHz
//
// Timer0 used to generate 1ms Interrupt
// prescaler required is 16
// Timer0 start value is 131 or 0x83 hex
//
// 7SEG will be updated ever 20ms based on - while (_7SEG_Update >= 20)
//
// If you want to see the update rate slowly then make this a larger number i.e 50 would = 50ms
long ADC_Value;
unsigned short digit_control = 0; // 7SEG Lower / Upper selection control
unsigned short _7SEG_Update = 0; // 7SEG update rate control
unsigned short Digit1 = 0, Digit2 = 0, Digit3 = 0, Digit4 = 0; // Holders for 7SEG data values
const unsigned char MASK[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void Interrupt() {
if(INTCON.T0IF == 1) // check that timer0 overflow is reason for ISR.
// even though there is only one Interrupt source
// trigger enabled, it is good programming practice to
// test why we have arrived at the ISR.
{
TMR0 = 0x83; // Reset Timer to Start Value
_7SEG_Update++; // add 1 to update rate control
INTCON.T0IF = 0; // Clear timer0 overflow flag
} // exit if
}// exit ISR
void _Update_7SEG_Write (void)
{
//PORTA = 0; // turn off both 7SEG
//delay_us(400);
switch (digit_control)
{
case 1: PORTD=MASK[Digit1]; // Data value for first 7SEG
PORTA = 0; // Turn OFF all 7SEG
Delay_us(50); // data setup Delay
PORTA.B0 = 1; // turn on first 7SEG
break; // Exit Case
case 2: PORTD=MASK[Digit2]; // Data value for second 7SEG
PORTA = 0; // Turn OFF all 7SEG
Delay_us(50); // data setup Delay
PORTA.B1 = 1; // turn on second 7SEG
break; // Exit Case
case 3: PORTD=MASK[Digit3]; // Data value for third 7SEG
PORTA = 0; // Turn OFF all 7SEG
Delay_us(50); // data setup Delay
PORTA.B2 = 1; // turn on third 7SEG
break; // Exit Case
case 4: PORTD=MASK[Digit4]; // Data value for fourth 7SEG
PORTA = 0; // Turn OFF all 7SEG
Delay_us(50); // data setup Delay
PORTA.B3 = 1; // turn on fourth 7SEG
break; // Exit Case
}// exit switch
}// exit Function
void main()
{
CM1CON0 = 0x00; // Comparator 1 set off
CM2CON0 = 0x00; // Comparator 2 set off
CM2CON1 = 0x02; // Comparator 2 Timer1 Control register default set
ADCON0 = 0x00; // ADC off
ADCON1 = 0x80; // ADC right justified
ANSEL = 0; // ALL set as Digital I/O
ANSELH = 0; // ALL set as Digital I/O
//ADC_Init(); // Initialize ADC module with default settings
PORTA = 0x00; // set PORTA all logic zero
PORTB = 0x00; // set PORTB all logic zero
PORTC = 0x00; // set PORTC all logic zero
PORTD = 0x00; // set PORTD all logic zero
PORTE = 0x00; // set PORTE all logic zero
TRISA = 0x00; // set PORTA all bits as output
TRISB = 0x00; // set PORTB as all output
TRISC = 0x00; // set PORTC as all output
TRISD = 0x00; // set PORTD as all output
TRISE = 0x04; // set PORTE as lower 3 bits output, MCLR is external
OPTION_REG.T0CS = 0; // Bit5 Timer0 clock source select bit [0 = FOSC/4 1 = T0CKI]
OPTION_REG.T0SE = 0; // Bit4 Timer0 source edge select bit [0 = Low to High 1 = High to Low]
OPTION_REG.PSA = 0; // Bit3 Prescalar Assignment bit [0 = Timer0 1 = WDT]
OPTION_REG.PS2 = 0; // Bit2 Prescalar Rate Select set to 1:16
OPTION_REG.PS1 = 1; // Bit1 Prescalar Rate Select
OPTION_REG.PS0 = 1; // Bit0 Prescalar Rate Select
INTCON = 0; // Clear INTCON
TMR0 = 0x83; // Timer0 start value
INTCON.T0IF = 0; // Clear Timer0 Overflow interrupt Flag
INTCON.T0IE = 1; // enable timer0 Interrupt
INTCON.GIE = 1; // enable Global interrupts
do
{
//ADC_Value = ADC_Get_Sample(0); // read analog value from ADC module channel 0
// ch0 is your choice of Analog input and will
// be ok for you as your digit control is on PORTB
ADC_Value = 10;
ADC_Value = ADC_Value * 352;
Digit4 = ADC_Value / 1000u ; // extract thousands digit
Digit3 = (ADC_Value / 100u) % 10u; // extract hundreds digit
Digit2 = (ADC_Value / 10u) % 10u; // extract tens digit
Digit1 = ADC_Value % 10u; // extract ones digit
if (_7SEG_Update >= 20) // Run 7SEG update every 15ms, reduce number for fast update rate
{
_7SEG_Update = 0; // Clear the update rate control
digit_control++; // controls which 7SEG will be updated
if (digit_control > 4) // only using 3 digits from the 4 available
{ // makes sure we are using 1, 2, 3
digit_control = 1; // this is used to drive the _7SEG_Write
} // case statement
_Update_7SEG_Write(); // call the 7SEG update routine
} // 7SEG update loop
}while(1);
}
- 4_digit_7seg.jpg (145.26 KiB) Viewed 4596 times
obviously ypu will need to alter the code for your pic and take from it what you wish.
I am a little concerned about safety... what ac voltage level are you applying to your pic ADC