|
|
View previous topic :: View next topic |
Author |
Message |
rosiley
Joined: 29 May 2014 Posts: 18 Location: Brasil
|
Problem the use two max 7219 with pic 18f4553 |
Posted: Tue Apr 26, 2016 1:11 pm |
|
|
Hello, I have a pic 18f4553 , where I'll read the AN0 and AN1 channels. They must show the values in two chip MAX7219 and the max1 show the value of AN0 channel and max2 show the value of AN1 channel. I made some modifications in the code with the help of our friend pcm programmer which gave me some policies that will help a lot but had no effect. I put the code here so you guys can analyze and see where I'm going wrong.
Obs . I closed the other topic as it was very messy and I did not understand anything.
Code: | #include <18F4553.h> // Includes header file PIC 18F4553
#device ADC = 12 //Sets 12 bits for the result of the AD conversion
#use delay (clock=20000000) /*Set the frequency of the crystal to calculate
..of delays */
#use spi(do=pin_D0,clk=pin_D2,bits=16,load_active=1,load=pin_D1,idle=1, stream=MAX1)
#use spi(do=pin_C0,clk=pin_C2,bits=16,load_active=1,load=pin_C1,idle=1, stream=MAX2)
//bits control configuration
#fuses HS //High Speed Crystal Oscillator
#fuses NOWDT //Watch Dog Timer disabled
#fuses PUT
#fuses BROWNOUT
#fuses NOLVP //Single-Supply ICSP disabled
// It shows the value of the AD converter
int32 hc1, hc2;
// It shows the value of Conversion
int32 hc1result;
int32 hc2result;
// The bits to display configuration in the 7-segment display
int address, data, adqnum, digit[5];
int16 packetmax;
// Packet transmission via spi to the max
void maxsend(int8 channel)
{ //routine for send information to the max
packetmax=make16(address,data); //make a 16 bit variable direcc byte high, dato byte low
if(channel == 1)
spi_xfer(MAX1, packetmax); //transfer using spi software
if(channel == 2)
spi_xfer(MAX2, packetmax);
}
// Configuration properties MAX7219
void maxsetup()
{
// Initialize the first MAX7219. The channel parameter = 1.
address=0x00, data=0x00, maxsend(1); // No-Operation
address=0x09, data=0xff, maxsend(1); // Decode-Mode Register Examples (Address (Hex) = 0xX9)
address=0x0a, data=0x0f, maxsend(1); // Intensity Register Format (Address (Hex) = 0xXA)
address=0x0b, data=0x05, maxsend(1); // Scan-Limit Register Format (Address (Hex) = 0xXB)
address=0x0f, data=0x01, maxsend(1); // Display-Test Register Format(Address (Hex) = 0xXF)
address=0x0c, data=0x01, maxsend(1); // Shutdown Register Format (Address (Hex) = 0xXC)
// Initialize the second MAX7219. The channel parameter = 2.
address=0x00, data=0x00, maxsend(2); // No-Operation
address=0x09, data=0xff, maxsend(2); // Decode-Mode Register Examples (Address (Hex) = 0xX9)
address=0x0a, data=0x0f, maxsend(2); // Intensity Register Format (Address (Hex) = 0xXA)
address=0x0b, data=0x05, maxsend(2); // Scan-Limit Register Format (Address (Hex) = 0xXB)
address=0x0f, data=0x01, maxsend(2); // Display-Test Register Format(Address (Hex) = 0xXF)
address=0x0c, data=0x01, maxsend(2); // Shutdown Register Format (Address (Hex) = 0xXC)
}
// The following lines are used for the digits
void algebra_digits()
{
// Initialize the first line 7 segments display.. The channel parameter = 1.
digit[0] = hc1result/1000;
digit[1] = ((hc1result % 1000)*10)/1000;
digit[2] = ((((hc1result % 1000)*10) % 1000)*10)/1000;
digit[3] = ((((((hc1result % 1000)* 10) % 1000) * 10) % 1000 )* 10) / 1000;
digit[4] = ((((((((hc1result % 1000)* 10) % 1000) * 10) % 1000) * 10) % 1000)* 10) / 1000;
// Initialize the second line 7 segments display. The channel parameter = 2.
digit[0] = hc2result/1000;
digit[1] = ((hc2result % 1000)*10)/1000;
digit[2] = ((((hc2result % 1000)*10) % 1000)*10)/1000;
digit[3] = ((((((hc2result % 1000)* 10) % 1000) * 10) % 1000 )* 10) / 1000;
digit[4] = ((((((((hc2result % 1000)* 10) % 1000) * 10) % 1000) * 10) % 1000)* 10) / 1000;
}
#INT_TIMER0 // Policy int the indetificação . Timer 0
void Trata_t0() // Function for treatment of Timer 0
{
tempo++; // Increments the variable time every 25ms
if (tempo >= 80) // If time > = 80 <=> 2 seconds ?
{
tempo = 0; // Returns the variable time 0
}
SET_TIMER0(61); // Returns the initial value to the Timer 0
}
void main()
{
// Set the analog inputs AN0 to AN1
SETUP_ADC_PORTS(AN0_TO_AN1|VSS_VREF);
// Use the internal clock to the time of acquisition
SETUP_ADC(ADC_CLOCK_Internal);
// Enable global interrupt
Enable_Interrupts(GLOBAL);
// Enables interruption by receiving data in serial
Enable_Interrupts(INT_RDA);
// Enables interruption by overflow of Timer 0
ENABLE_INTERRUPTS(INT_TIMER0);
/* Set Timer 0 Prescaler to increase the machine cycle of 1 : 256 and
mode 8 bits */
SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
// Start the Timer 0 with the value 61 - Interruption every 25ms
SET_TIMER0(61);
maxsetup();
delay_ms(3000); // Delays the start of the display
/* Makes cleaning all the rec variable and makes the controleb maga indexes 0 */
for(cont = 0; cont < 5; cont++) rec[cont] = '\0';
cont = 0;
//Loop principal
while(true)
{
for(adqnum=1;adqnum<=100;adqnum++)
{ //collect 100 samples, I usually do this, u can use your favorite method
hc1=hc1+read_adc(); //for acquisition.
delay_us(20);
hc2=hc2+read_adc(); //for acquisition.
delay_us(20);
}
hc1=hc1*10;
algebra_digits(); //call algebra routine to get each digit
address=0x01, data=(digit[0] | 0b10000000), maxsend(1); //use OR for adding decimal point
address=0x02, data=digit[1], maxsend(1);
address=0x03, data=digit[2], maxsend(1);
address=0x04, data=digit[3], maxsend(1);
address=0x05, data=digit[4], maxsend(1);
hc1=0; //clean hc1
hc2=hc2*10;
algebra_digits(); //call algebra routine to get each digit
address=0x01, data=(digit[0] | 0b10000000), maxsend(2); //use OR for adding decimal point
address=0x02, data=digit[1], maxsend(2);
address=0x03, data=digit[2], maxsend(2);
address=0x04, data=digit[3], maxsend(2);
address=0x05, data=digit[4], maxsend(2);
hc2=0; //clean hc2
SET_ADC_CHANNEL(0); //Sets the read channel 0
delay_us(100); //Channel adjustment time (required)
hc1 = READ_ADC(); //Does the AD conversion and saves it in the variable ad0
SET_ADC_CHANNEL(1); //Sets the read channel 1
delay_us(100); //Channel adjustment time (required)
hc2 = READ_ADC(); //Does the AD conversion and saves it in the variable ad1
hc1result = (hc1 * 5000) /4095;
hc2result = (hc2 * 5000) /4095;
delay_ms(100); //Delay 100ms
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 26, 2016 6:05 pm |
|
|
1. You didn't compile your program and fix the compiler errors before
you posted it. It gives these errors:
Quote: |
*** Error 12 "PCH_Test.c" Line 84(1,6): Undefined identifier tempo
*** Error 12 "PCH_Test.c" Line 85(5,10): Undefined identifier tempo
*** Error 12 "PCH_Test.c" Line 88(5,10): Undefined identifier tempo
*** Error 12 "PCH_Test.c" Line 115(5,9): Undefined identifier cont
*** Error 12 "PCH_Test.c" Line 115(15,19): Undefined identifier cont
*** Error 12 "PCH_Test.c" Line 115(25,29): Undefined identifier cont
*** Error 12 "PCH_Test.c" Line 116(1,5): Undefined identifier cont
7 Errors, 0 Warnings.
Build Failed. |
2. You didn't tell us what is wrong with the program output. What do
you see on the 5-digit, 7-segment displays ? What do expect to see, if it
was working correctly ?
3. The following code reads 100 samples from each A/D channel,
but there is no code to change the A/D channel between 0 and 1.
You left out the set_adc_channel() lines.
Code: |
for(adqnum=1;adqnum<=100;adqnum++)
{ //collect 100 samples, I usually do this, u can use your favorite method
hc1=hc1+read_adc(); //for acquisition.
delay_us(20);
hc2=hc2+read_adc(); //for acquisition.
delay_us(20);
}
|
4. A 12-bit A/D has a maximum possible output of 4095.
The result of adding 100 samples (and then multiplying the result * 10)
will give you a maximum value of 4095 * 100 * 10 = 4095000.
That's 7 digits. But your display can only show 5 digits. It won't work.
5. Below, you are enabling Rx interrupts for the hardware UART:
Code: | Enable_Interrupts(INT_RDA); |
But you don't have an #int_rda function to handle the interrupts. In fact,
you don't even have a #use rs232() statement to enable the UART.
Why enable INT_RDA ? You're not even using the UART.
6. There are other minor bugs.
7. You are now on your 3rd PIC. First was 12F683, next was 16F877A,
now you have 18F4553. This really looks like a Proteus project. |
|
|
rosiley
Joined: 29 May 2014 Posts: 18 Location: Brasil
|
|
Posted: Tue Apr 26, 2016 6:19 pm |
|
|
My friend good night .
Sorry about the mess but now follows the complete code and running but with the errors said at the beginning of the post, I will make the changes that you mentioned and see what will happen.
At first I started using the 12F683, 16F877A, but the final is the 18f4553 .
Code: |
#include <18F4553.h> // Includes header file PIC 18F4553
#device ADC = 12 //Sets 12 bits for the result of the AD conversion
#use delay (clock=20000000) /*Set the frequency of the crystal to calculate
..of delays */
#use spi(do=pin_D0,clk=pin_D2,bits=16,load_active=1,load=pin_D1,idle=1, stream=MAX1)
#use spi(do=pin_C0,clk=pin_C2,bits=16,load_active=1,load=pin_C1,idle=1, stream=MAX2)
//bits control configuration
#fuses HS //High Speed Crystal Oscillator
#fuses NOWDT //Watch Dog Timer disabled
#fuses PUT
#fuses BROWNOUT
#fuses NOLVP //Single-Supply ICSP disabled
//Settings for serial communication
#use RS232 (Baud=9600, xmit = PIN_C6, rcv = PIN_C7)
// It shows the value of the AD converter
int32 hc1, hc2, tmp, prs;
// It shows the value of Conversion
int32 hc1result;
int32 hc2result;
int32 tmpresult;
int32 prsresult;
// The bits to display configuration in the 7-segment display
int address, data, adqnum, digit[5];
int16 packetmax;
// Packet transmission via spi to the max
void maxsend(int8 channel)
{ //routine for send information to the max
packetmax=make16(address,data); //make a 16 bit variable direcc byte high, dato byte low
if(channel == 1)
spi_xfer(MAX1, packetmax); //transfer using spi software
if(channel == 2)
spi_xfer(MAX2, packetmax);
}
// Configuration properties MAX7219
void maxsetup()
{
// Initialize the first MAX7219. The channel parameter = 1.
address=0x00, data=0x00, maxsend(1); // No-Operation
address=0x09, data=0xff, maxsend(1); // Decode-Mode
address=0x0a, data=0x0f, maxsend(1); // Intensity
address=0x0b, data=0x05, maxsend(1); // Scan-Limit
address=0x0f, data=0x01, maxsend(1); // Display-Test
address=0x0c, data=0x01, maxsend(1); // Shutdown
// Initialize the second MAX7219. The channel parameter = 2.
address=0x00, data=0x00, maxsend(2); // No-Operation
address=0x09, data=0xff, maxsend(2); // Decode-Mode
address=0x0a, data=0x0f, maxsend(2); // Intensity
address=0x0b, data=0x05, maxsend(2); // Scan-Limit
address=0x0f, data=0x01, maxsend(2); // Display-Test
address=0x0c, data=0x01, maxsend(2); // Shutdown
}
// The following lines are used for the digits
void algebra_digits()
{
// Initialize the first line 7 segments display.. The channel parameter = 1.
digit[0] = hc1result/1000;
digit[1] = ((hc1result % 1000)*10)/1000;
digit[2] = ((((hc1result % 1000)*10) % 1000)*10)/1000;
digit[3] = ((((((hc1result % 1000)* 10) % 1000) * 10) % 1000 )* 10) / 1000;
digit[4] = ((((((((hc1result % 1000)* 10) % 1000) * 10) % 1000) * 10) % 1000)* 10) / 1000;
// Initialize the second line 7 segments display. The channel parameter = 2.
digit[0] = hc2result/1000;
digit[1] = ((hc2result % 1000)*10)/1000;
digit[2] = ((((hc2result % 1000)*10) % 1000)*10)/1000;
digit[3] = ((((((hc2result % 1000)* 10) % 1000) * 10) % 1000 )* 10) / 1000;
digit[4] = ((((((((hc2result % 1000)* 10) % 1000) * 10) % 1000) * 10) % 1000)* 10) / 1000;
}
/******************************************************************************
Control variables:
cont = index of control for serial reception ;
time = time information within 2 seconds
*******************************************************************************/
int cont=0, tempo=0;
int rec[5]; // For serial data reception Variable
#INT_RDA // Identficação Policy w / int . the serial reception
void rec_serial() // Receiving data processing function
{
rec[cont] = getc(); /* Read the data from the serial and stores it in the rec position
(Index) informed cont */
if (rec[cont] == 0x0D) // Check if the data received is equal to CR ( 0x0D )
{
/* After received all serial data, it makes cleaning the whole variable and rec
returns the contents of control in cont 0 */
for(cont = 0; cont < 5; cont++) rec[cont] = '\0';
cont = 0;
}
else
/* If not yet received all of the data control increments the variable maga index */
cont++;
}
#INT_TIMER0 // Policy int the indetificação . Timer 0
// Make the LED on the door D3 blinking, indicating that the processor is running
void PiscaLED()
{
static boolean PiscaLed; // To flash the LED.
static int contador; // To tell the time of 1 second.
set_timer0(131-get_timer0());
contador++;
if(contador == 125) //If said 125 (1 second ) .
{
contador=0; // Zero count.
PiscaLed = !PiscaLed; // Invert bit;
output_bit(pin_D3, PiscaLed); // On / Off LED .
}
}
void Trata_t0() // Function for treatment of Timer 0
{
tempo++; // Increments the variable time every 25ms
if (tempo >= 80) // If time > = 80 <=> 2 seconds ?
{
tempo = 0; // Returns the variable time 0
}
SET_TIMER0(61); // Returns the initial value to the Timer 0
}
// Protocol Format = HC1:0000 : HC2:0000 : TMP:0000 : depht:0000
void escreve_serial() // Protocol sending function for serial
{
printf("HC1:%4lu",hc1result); // Send conversion data A/D to display voltage
printf(":"); // Protocol Control
printf("HC2:%4lu",hc2result); // Send conversion data A/D to display voltage
printf(":"); // Protocol Control
printf("TMP:%4lu",tmpresult); // Send conversion data A/D to display voltage
printf(":"); // Protocol Control
printf("DEPHT:%4lu",prsresult); // Send conversion data A/D to display voltage
printf("\n\r"); // Protocol Control
}
void main()
{
// Set the analog inputs AN0 to AN4
SETUP_ADC_PORTS(AN0_TO_AN4|VSS_VREF);
// Use the internal clock to the time of acquisition
SETUP_ADC(ADC_CLOCK_Internal);
// Enable global interrupt
Enable_Interrupts(GLOBAL);
// Enables interruption by receiving data in serial
Enable_Interrupts(INT_RDA);
// Enables interruption by overflow of Timer 0
ENABLE_INTERRUPTS(INT_TIMER0);
/* Set Timer 0 Prescaler to increase the machine cycle of 1 : 256 and mode 8 bits */
SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
// Start the Timer 0 with the value 61 - Interruption every 25ms
SET_TIMER0(61);
maxsetup();
delay_ms(3000); // Delays the start of the display
/* Makes cleaning all the rec variable and makes the controleb maga indexes 0 */
for(cont = 0; cont < 5; cont++) rec[cont] = '\0';
cont = 0;
//Loop principal
while(true)
{
for(adqnum=1;adqnum<=100;adqnum++)
{
//collect 100 samples, I usually do this, u can use your favorite method
hc1=hc1+read_adc(); //for acquisition.
delay_us(20);
hc2=hc2+read_adc(); //for acquisition.
delay_us(20);
}
hc1=hc1*10;
algebra_digits(); //call algebra routine to get each digit
address=0x01, data=(digit[0] | 0b10000000), maxsend(1); //use OR for adding decimal point
address=0x02, data=digit[1], maxsend(1);
address=0x03, data=digit[2], maxsend(1);
address=0x04, data=digit[3], maxsend(1);
address=0x05, data=digit[4], maxsend(1);
hc1=0; //clean hc1
hc2=hc2*10;
algebra_digits(); //call algebra routine to get each digit
address=0x01, data=(digit[0] | 0b10000000), maxsend(2); //use OR for adding decimal point
address=0x02, data=digit[1], maxsend(2);
address=0x03, data=digit[2], maxsend(2);
address=0x04, data=digit[3], maxsend(2);
address=0x05, data=digit[4], maxsend(2);
hc2=0; //clean hc2
SET_ADC_CHANNEL(0); //Sets the read channel 0
delay_us(100); //Channel adjustment time (required)
hc1 = READ_ADC(); //Does the AD conversion and saves it in the variable ad0
SET_ADC_CHANNEL(1); //Sets the read channel 1
delay_us(100); //Channel adjustment time (required)
hc2 = READ_ADC(); //Does the AD conversion and saves it in the variable ad1
SET_ADC_CHANNEL(2); //Sets the read channel 2
delay_us(100); //Channel adjustment time (required)
tmp = READ_ADC(); //Does the AD conversion and saves it in the variable ad2
SET_ADC_CHANNEL(4); //Sets the read channel 4
delay_us(100); //Channel adjustment time (required)
prs = READ_ADC(); //Does the AD conversion and saves it in the variablel ad4
hc1result = (hc1 * 5000) /4095;
hc2result = (hc2 * 5000) /4095;
tmpresult = (tmp * 5000) /4095;
prsresult = (prs * 5000) /4095;
escreve_serial(); //Sends data over a serial
delay_ms(100); //Delay 100ms
}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Tue Apr 26, 2016 7:22 pm |
|
|
this...
SETUP_ADC(ADC_CLOCK_Internal)
If memory serves me right this is usually ONLY for when a PIC is asleep. Be sure to read the valid options for ADC clock selection, in the ADC chapter of the data sheet. Microchip print a chart or table of processor speed vs adc clock speeds.
then there's this 'math'...
Code: | digit[1] = ((hc2result % 1000)*10)/1000; |
it looks like *10/1000 should be reduced, though perhaps the compiler does it for you...it just 'looks' complicated.
same holds true for the *5000/4095 ; math
Jay |
|
|
rosiley
Joined: 29 May 2014 Posts: 18 Location: Brasil
|
|
Posted: Fri Apr 29, 2016 10:35 am |
|
|
Good afternoon everyone.
With the help of I managed to solve the problem here and also did cleaning in the code that was much useless information, then I ask the moderator to close this topic.
And before it is closed, do the following question: How do I get the max2 receive information from other analog inputs when I trigger a button on RB0 input of the pic ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Apr 29, 2016 12:45 pm |
|
|
Topics are never 'closed' (except if wildly off topic etc.).
All that is needed is for _you_ as the author, to edit the title, to include [Solved]. |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Fri Apr 29, 2016 1:42 pm |
|
|
rosiley wrote: | How do I get the max2 receive information from other analog inputs when I trigger a button on RB0 input of the pic ? |
Hi,
First, I would look for PCM programmers 'Button' function. This is a routine that does switch debouncing on the signal generated by an electromechanical switch. Use this function to toggle a variable that determines which A/D channel you are reading. I'd also make a function for your A/D reading code to eliminate a lot of redundancy and clean up your code a bit.
Something like this:
Code: |
int16 Read_Analog(int8 Channel)
{
SET_ADC_CHANNEL(Channel); //Sets the read channel
delay_us(100); //Channel adjustment time (required)
hc1 = READ_ADC(); //Does the AD conversion
return(hc1);
}
|
to use this code you would do this:
Code: |
hc1 = Read_Analog(0);
|
_________________ John
If it's worth doing, it's worth doing in real hardware! |
|
|
rosiley
Joined: 29 May 2014 Posts: 18 Location: Brasil
|
|
Posted: Sat Apr 30, 2016 7:08 am |
|
|
Sorry, I'm not understand your explanation. |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Sun May 01, 2016 11:29 am |
|
|
Hi,
Which part? What did you try?
Here is PCM's 'button' function: http://www.ccsinfo.com/forum/viewtopic.php?t=23837&highlight=button
To use it you could do something like this:
Code: |
if(button(PIN_B0, 0, 50, 10, B0, 1))
{
if (bInputFlag)
bInputFlag = False;
else
bInputFlag = True;
}
|
This will toggle a variable, bInputFlag, which you would then use to determine which analog input you were sampling:
Code: |
if(bInputFlag)
hc1 = Read_Analog(0);
else
hc1 = Read_Analog(1);
|
There are more compact ways to write this code, but I'm doing it this way so it's (hopefully) very clear! _________________ John
If it's worth doing, it's worth doing in real hardware! |
|
|
|
|
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
|