\n","author":{"@type":"Person","name":"CrazyProgrammer"},"upvoteCount":1,"answerCount":2,"acceptedAnswer":{"@type":"Answer","text":"
As a solution, according to the code given by @Kozmotronik, the problem was solved when 74hc595 was used instead of 7447.
\nThis is the solved code and scheme:
\n\n#include <xc.h>\n\n#pragma config FOSC = INTRCIO // Internal oscillator\n#pragma config WDTE = OFF // Watchdog Timer disabled\n#pragma config PWRTE = OFF // Power-up Timer disabled\n#pragma config MCLRE = ON // GP3/MCLR pin function is digital I/O\n#pragma config BOREN = ON // Brown-out Reset enabled\n#pragma config CP = OFF // Code Protection disabled\n#pragma config CPD = OFF // Data Memory Code Protection disabled\n\n#define _XTAL_FREQ 4000000\n\n#define ST_CP GP4\n#define DS GP2\n#define SH_CP GP1\n\n\nunsigned int adc_value = 0;\nfloat volt=0;\nuint8_t LED [10]={\n 0xE7, //0 0xE7\n 0x21, //1\n 0xDB, //2 0xD3\n 0x6B, //3 0xD6\n 0x3D, // 4 0xB4\n 0x7E, // 5 0x76\n 0xEE, //6\n 0x23, //7 0xE4\n 0xEF, //8\n 0x7F, //9 0xF6\n};\n\nvoid spi_shift_out(uint8_t data) {\n uint8_t i;\n for (i = 0; i < 8; i++) {\n if (data & (1 << (7 - i))) {\n DS = 1;\n } else {\n DS = 0;\n }\n \n SH_CP = 1;\n __delay_us(1);\n SH_CP = 0;\n }\n \n ST_CP = 1;\n __delay_us(1);\n ST_CP = 0; \n}\n\nvoid display_digit(uint8_t digit) {\n spi_shift_out(LED[digit]);\n}\n\nvoid main(void) {\n GPIO = 0; // Clear output latches\n CMCON = 7; // Turn off analog comparators\n TRISIO = 1; // GP0 and GP3 (GP3 is an only input pin) are input and other pins are output\n ANSEL = 0x21; \n ADCON0 = 0x81; \n while (1) {\n ADCON0bits.GO = 1;\n while (ADCON0bits.GO);\n adc_value = (ADRESH <<8) + ADRESL;\n volt=(adc_value*5)/1023;\n if (volt >= 0 && adc_value < 0.99) {\n display_digit(0);\n } else if (volt >= 1.0 && volt < 1.99) {\n display_digit(1);\n } else if (volt >= 2.0 && volt < 2.99) {\n display_digit(2);\n } else if (volt >= 3.0 && volt < 3.99) {\n display_digit(3);\n } else if (volt >= 4.0 && volt <= 4.99) {\n display_digit(4);\n } else {\n display_digit(4);\n }\n __delay_ms(100);\n }\n\n return;\n}\n
\n\n","author":{"@type":"Person","name":"CrazyProgrammer"},"upvoteCount":-1}}}Reputation: 19
This Analog data is read and the number 1-5 is shown on the 7 segment common anode display with 7447, but I can't set this number for analog value because I can't show analog values or output I wrote this code in MPLAB X IDE.
#include <xc.h>
#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF
#define _XTAL_FREQ 4000000
#define HIGH 1
#define LOW 0
unsigned int adc_value=0;
void main(void) {
TRISIObits.TRISIO0 = 1;
TRISIObits.TRISIO1 = 0;
TRISIObits.TRISIO2 = 0;
TRISIObits.TRISIO4 = 0;
TRISIObits.TRISIO5 = 0;
ANSELbits.ADCS2 = 0;
ANSELbits.ADCS1 = 0;
ANSELbits.ADCS0 = 0;
ANSELbits.ANS0 = 1;
ADCON0bits.CHS0 = 0;
ADCON0bits.CHS1 = 0;
ADCON0bits.ADON = 1;
ADCON0bits.GO = 1;
ADCON0bits.ADFM = 1;
while(1) {
ADON = 1;
GO_DONE = 1;
while(GO_DONE);
adc_value = (((unsigned int) ADRESH << 8) + ADRESL);
ADON = 0;
if (adc_value >= 0 && adc_value <= 200) {
GP4 = 0;
GP5 = 0;
GP2 = 0;
GP1 = 0;
} else if (adc_value > 200 && adc_value <= 400) {
GP4 = 0;
GP5 = 0;
GP2 = 0;
GP1 = 1;
} else if (adc_value > 400 && adc_value <= 600) {
TRISIObits.TRISIO4 = 0;
TRISIObits.TRISIO5 = 0;
TRISIObits.TRISIO2 = 1;
TRISIObits.TRISIO1 = 0;
} else if (adc_value > 600 && adc_value <= 800) {
TRISIObits.TRISIO4 = 0;
TRISIObits.TRISIO5 = 0;
TRISIObits.TRISIO2 = 1;
TRISIObits.TRISIO1 = 1;
} else if (adc_value > 800 && adc_value <= 1023) {
TRISIObits.TRISIO4 = 0;
TRISIObits.TRISIO5 = 1;
TRISIObits.TRISIO2 = 0;
TRISIObits.TRISIO1 = 0;
} else {
TRISIObits.TRISIO4 = 1;
TRISIObits.TRISIO5 = 1;
TRISIObits.TRISIO2 = 1;
TRISIObits.TRISIO1 = 1;
}
__delay_ms(100);
}
return;
}
my aim in this project is to print the number between 0-5 on the 7 segment common anode display according to the analog data between 0-1023, but I could not solve this problem.
Upvotes: 1
Views: 111
Reputation: 19
As a solution, according to the code given by @Kozmotronik, the problem was solved when 74hc595 was used instead of 7447.
This is the solved code and scheme:
#include <xc.h>
#pragma config FOSC = INTRCIO // Internal oscillator
#pragma config WDTE = OFF // Watchdog Timer disabled
#pragma config PWRTE = OFF // Power-up Timer disabled
#pragma config MCLRE = ON // GP3/MCLR pin function is digital I/O
#pragma config BOREN = ON // Brown-out Reset enabled
#pragma config CP = OFF // Code Protection disabled
#pragma config CPD = OFF // Data Memory Code Protection disabled
#define _XTAL_FREQ 4000000
#define ST_CP GP4
#define DS GP2
#define SH_CP GP1
unsigned int adc_value = 0;
float volt=0;
uint8_t LED [10]={
0xE7, //0 0xE7
0x21, //1
0xDB, //2 0xD3
0x6B, //3 0xD6
0x3D, // 4 0xB4
0x7E, // 5 0x76
0xEE, //6
0x23, //7 0xE4
0xEF, //8
0x7F, //9 0xF6
};
void spi_shift_out(uint8_t data) {
uint8_t i;
for (i = 0; i < 8; i++) {
if (data & (1 << (7 - i))) {
DS = 1;
} else {
DS = 0;
}
SH_CP = 1;
__delay_us(1);
SH_CP = 0;
}
ST_CP = 1;
__delay_us(1);
ST_CP = 0;
}
void display_digit(uint8_t digit) {
spi_shift_out(LED[digit]);
}
void main(void) {
GPIO = 0; // Clear output latches
CMCON = 7; // Turn off analog comparators
TRISIO = 1; // GP0 and GP3 (GP3 is an only input pin) are input and other pins are output
ANSEL = 0x21;
ADCON0 = 0x81;
while (1) {
ADCON0bits.GO = 1;
while (ADCON0bits.GO);
adc_value = (ADRESH <<8) + ADRESL;
volt=(adc_value*5)/1023;
if (volt >= 0 && adc_value < 0.99) {
display_digit(0);
} else if (volt >= 1.0 && volt < 1.99) {
display_digit(1);
} else if (volt >= 2.0 && volt < 2.99) {
display_digit(2);
} else if (volt >= 3.0 && volt < 3.99) {
display_digit(3);
} else if (volt >= 4.0 && volt <= 4.99) {
display_digit(4);
} else {
display_digit(4);
}
__delay_ms(100);
}
return;
}
Upvotes: -1
Reputation: 2520
You haven't configured GPIO<1:5> as digital IOs. That's why you cannot control them.
According to the device's datasheet you muxt configure them using the CMCON
and the ANSEL
register.
The CMCON
register controls the built in analog comparators that uses several pins that connect the internal hardware to the outside world via the GP0 (CIN+)
, GP1 (CIN-)
and GP2 (COUT)
pins respectively. So you need to turn off the comparators hardware first by setting the CM2:CM0
bits to 7 (111 in binary).
CMCON = 7;
The ANSEL
register is where you can tell the micro what pins you wanna use for ADC operation. In your case, since you use only the AN0 (GP0)
and the rest must be configured as digital. What you wanna do is to set the corresponding ANSx bit for the pin you wanna use as analog input (you use AN0
hence you must set ANS0
), and the rest of the ANSx
bits must be set to 0 to use other pins as digital IO.
ANSEL = 1;
So if we wrap up the information above and merge it into your code, and also tidy up your code, the final code should look like this:
#include <xc.h>
#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF
#define _XTAL_FREQ 4000000
#define HIGH 1
#define LOW 0
void setupInputs() {
GPIO = 0; // Clear output latches
CMCON = 7; // Turn off analog comparators
TRISIO = 1; // GP0 and GP3 (GP3 is an only input pin) are input and other pins are output
}
void setupADC() {
ANSEL = 0x21; // Set the GP0 pin as analog input and the rest is digital IO
// and use the internal RC osc for ADC
ADCON0 = 0x81; // Right justify, sample CH0, ADC turn on
}
unsigned int getAnalogValueOnCh0() {
ADCON0bits.GO = 1;
while(ADCON0bits.GO)
; // Wait for the ADC conversion to complete
return (unsigned int) ( ADRESH << 8) + ADRESL;
}
void setDisplay(char value) {
GP1 = value & 1;
GP2 = (value & 2) >> 1;
GP4 = (value & 4) >> 2;
GP5 = (value & 8) >> 3;
}
void main(void) {
setupInputs();
setupADC();
setDisplay(0);
__delay_us(20); // See datasheet 7.2 A/D ACquisition Requirements
while(1) {
unsigned int adc_value = getAnalogValueOnCh0();
if (adc_value >= 0 && adc_value <= 200) {
setDisplay(0);
} else if (adc_value > 200 && adc_value <= 400) {
setDisplay(1);
} else if (adc_value > 400 && adc_value <= 600) {
setDisplay(2);
} else if (adc_value > 600 && adc_value <= 800) {
setDisplay(3);
} else if (adc_value > 800 && adc_value <= 1023) {
setDisplay(4);
} else {
setDisplay(5);
}
__delay_ms(100);
}
}
PS: You shoud have ranged the values in 1024 / 6 = 170 approx. But you sliced the ADC valur into the chunks of 200. You choose.
Upvotes: 3