|
|
View previous topic :: View next topic |
Author |
Message |
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
Problem using 12F510 A/D and GP ports |
Posted: Mon Feb 20, 2012 1:03 am |
|
|
12F510:
Concerning a new project design I have to do using the 12F510, I am having a "head banger time" trying to get GP ports to work and the fact that the A/D brings in erratic values from AN0. (0 to 5V from a pot) and
attempts to toggle GP1 pin 6.... but doesn't toggle.
I have read the tables relative to the multi-functionality pins on the 12F510 :
table 3-2, 5-1, 5-5. But to no avail.
The program is really simple: but works erratic... anybody have a clue?
Code: |
#include <12F510.h> // ADC=10
#device adc=8
// CONFIGURATION WORD (fuses)
#FUSES INTRC, NOWDT, NOPROTECT, MCLR
#use delay(clock=8000000)
void main(void)
{
#ASM
MOVLW 0x84 // 1:32
OPTION // the T0CS bit in the OPTION register that must be clear,
#ENDASM
setup_timer_0(RTCC_DIV_16 | ENABLEPULLUPS);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
setup_comparator(NC_NC); // disable comparator output 0x00FF07
clrvar(); // a function that just clears ram vars.
#ASM
MOVLW 0b000001
TRIS GPIO // reg 6
MOVLW 0b000000
MOVWF OSCCAL // reg 5
MOVLW 0x42 // disable compare output WAS 5A
MOVWF CM1CON0 // reg 7
// setup_adc_ports(AN0_AN2); // AN0 AN2
MOVLW 0x81 // A/D AN0 Pin 7
MOVWF ADCON0 // reg 8
#ENDASM
read_adc(ADC_START_AND_READ); // read and clear
while(1){
clock();
check_float_status();
if(bit_test(ADCON0, 1) == 0){ // A/D AN0 0x80 0 = COMPLETE
set_adc_channel(0);
pot_value = read_adc(ADC_START_AND_READ);
//if(pot_value < 2){
// pot_value = 2; // the minimum value
//}
}
switch(main_state){ //
case 0:
if(bit_test(flag_reg_1, 0) ){
bit_clear(flag_reg_1, 0);
OUTPUT_LOW(PIN_B4); // GP4 pump off. Pin 3
OUTPUT_LOW(PIN_B1); // GP1 pin 6
main_state = 1;
}
break;
case 1: // Read Float switch
if(bit_test(flag_reg_1, 0) ){
bit_clear(flag_reg_1, 0);
OUTPUT_HIGH(PIN_B4); // GP4 pump on. Pin 3
OUTPUT_LOW(PIN_B1); // GP1 pin 6
main_state = 0;
}
break;
case 2: //
break;
default:
main_state = 0;
}
}
}
// ********************************************************
void clock(void)
{
if(get_timer0() == 0){
set_timer0(pot_value);
ms_cntr++;
if(ms_cntr > 30){ // x counts = 1 sec 2/21/2011
ms_cntr = 0;
seconds++;
bit_set(flag_reg_1, 0);
if(tog){
tog = 0;
OUTPUT_LOW(PIN_B1); // bit_clear(GPIO, GP1); // pin 6
}
else{
tog = 1;
OUTPUT_LOW(PIN_B1); // bit_set(GPIO, GP1); // pin 6
}
if(seconds == 60){
seconds = 0;
minutes++;
if(minutes == 60){
minutes = 0;
hours++;
if(hours == 24){ //
days++;
hours = 0; // bug fix 4/2/2011
if(days == 7){
days = 0; // reset to 0
pump_timer = 5; // 5 seconds 2/13/2012
}
}
}
}
}
}
}
void check_float_status(void)
{
//
if(bit_test(GPIO, 5) == 0){ // GP5 pin 2
OUTPUT_HIGH(PIN_B4); // GP4 pump on. Pin 3
anti_lock_sec = 0;
// float_switch_level is an unsigned long 0xF0 is just below 1/2 port value
}
} |
_________________ Jim Oram |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Mon Feb 20, 2012 5:16 am |
|
|
Start again.....
Several settings are wrong. For example, you have 'enable_pullups' in the setup for timer0. This is not a legal setting for timer0, so will result in it being setup wrong.
Then, you select an ADC channel, and immediately read it. _Wrong_. You _must_ allow Tacq, after selecting a channel, before reading it.
You are then throwing bits of unnecessary assembler into the code. I can't see one of these that is needed, unless you have a very old and faulty compiler.
You then feed '0' into OSCCAL - why?. The OSCCAL value has been set automatically by the compiler from the value stored in the chip, at boot time. Setting 0, just ensures the calibration will be wrong.
You don't show your variable declarations, so we can't even comment if these may be completely invalid for the operations you then perform on them.
Then there is the problem of the timer. You read it and test 'for' a value. Problem is that it will only read as zero, for 16 instructions. If your loops and branches to get here take longer than this, you _will_ miss the zero state.
Step back, throw away the assembler, and KISS.
I've done a simplified demo, showing how to avoid the timer problems, and how to just toggle two pins, dependant on the value read from a pot on AN2.
It works.
Code: |
#include <12F510.h>
#device adc=8
#FUSES NOWDT, INTRC, NOMCLR
#use delay(clock=8000000)
int1 flag=FALSE;
void tick(void) ;
void main() {
int8 state=0;
int8 pot_value;
setup_adc_ports(AN0_AN2);
setup_adc(ADC_CLOCK_DIV_8);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
setup_comparator(NC_NC);
set_adc_channel(0);
delay_us(10);
do {
pot_value=read_adc();
tick();
//An example of using a flag, rather than using bit_test
switch (state) {
case 0:
if (flag) {
flag=false;
output_low(PIN_B4);
output_low(PIN_B1);
state=1;
}
break;
case 1:
if (flag) {
flag=false;
output_high(PIN_B4);
output_high(PIN_B1);
state=1;
set_timer0(pot_value/2);
}
break;
}
delay_us(10); //ensure loop is not too fast for ADC to re-acquire
} while (TRUE);
}
void tick(void) {
int8 timer_val;
//How to avoid missing the timer - note now /32 not /16
timer_val=get_timer0();
if (bit_test(timer_val,7)) {
set_timer0(timer_val & 0x7F);
flag^=1;
}
}
|
Best Wishes |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
Problem with 12F510 and GP ports |
Posted: Mon Feb 20, 2012 6:39 am |
|
|
Hello Ttelmah, Thank you very kindly for the reply and sample code.
I will try it very soon, ....but first I will give you the variable definitions.... in case I have a problem there:
Code: |
//
int8 ms_cntr; //
int8 pump_timer; //
int8 anti_lock_sec; //
int8 pot_value; //
int8 antilock_function_timer; //
int8 antilock_pump_state; //
int8 main_state; //
int8 seconds; //
int8 minutes; //
int8 hours; //
int8 days; //
int8 tog;
//
// Flags register
int8 flag_reg_1; //
// 7 6 5 4 3 2 1 0
// | | | | | | | \- sec flag
// | | | | | | \ ---
// | | | | | \-------
// | | | | \---------- OP_TOGGLE;
// | | | \-------------
// | | \---------------- ANTILOCK_FLG1
// | \------------------- ANTILOCK_FLG2
// \----------------------
|
Thanks, Jim _________________ Jim Oram |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Mon Feb 20, 2012 9:05 am |
|
|
Realistically, on the flags, looks OK, but much better to just use int1's for the flags with names. So:
Code: |
int1 sec_flag = 0;
int1 OP_toggle;
int1 antilock_fllg1;
int1 antilock_flg2;
|
That way you can initialise them in the declaration (as I show on the first one), and avoid the probability of selecting the wrong bit accidentally!...
Let the compiler do it's job.
You talk about 'float_switch' being an unsigned long, hence I was puzzled about what types you were actually using....
Best Wishes |
|
|
Jim Oram
Joined: 01 Jan 2010 Posts: 24 Location: Charlotte
|
12F510 code corrections: |
Posted: Mon Feb 20, 2012 10:11 pm |
|
|
Ttelmah, Your point of using bit vars is well taken. I will do that.
Your recommended sample code works well. Thank you. However it did not work at first try, the variable state=1; was the same in both cases in your sample code.
I am now proceeding to bring the whole system up and running.
I will study your code recommendations and go over the architecture of the multi-function chip pins. Right now it is confusing to me how to know what to include, exclude, and what effects one function has on another.
The way I see it now is: turn everything off and then enable only what is required for an application.
If you have any insights, examples or tutorials that would make it easier to grasp the multi-layered features of the 12F series of chips would be welcome.
Thank You Very Kindly for your help.
Jim _________________ Jim Oram |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Tue Feb 21, 2012 2:43 am |
|
|
Yes, I Cut&Copied, and didn't change state in the second copy.
Good that you spotted it.
What you want to do, would be _much_ easier on a slightly larger chip. A device like the 12F675 (for example), supports interrupts, and even if you don't use them, this means the hardware will set a flag when the timer wraps. Avoids the problem of missing the '0' on the timer.
Given these slightly more modern chips are often cheaper than the older ones, well worth considering...
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|