|
|
View previous topic :: View next topic |
Author |
Message |
pic_micro
Joined: 07 Feb 2011 Posts: 26
|
how to separate a float number to display into MAX7456 |
Posted: Tue May 03, 2011 9:40 am |
|
|
I need help,
I working on the MAX7456 chip (overlay OSD)
I want to display a voltage such as 0-5 (include decimal point ex 3.5V) onto osd screen.
I can separate the number such as 1234 & display them onto osd with the following code
Code: | thousand = (n/1000); //1000s
hundred = ( n%1000)/100; // 100s digit
ten = ((n %1000)%100)/10; // 10s digit
one = (n %1000)%10; // 1s digit |
but I ran out of idea how to display a float number (3.5)
the number is a 10bit ADC from chn0 of pic-demo2 plus.
I use the following formula to calculate the voltage.
Code: |
volt = (n/1023) * 5;
|
Let say n = 716 which is volt = 3.5, how do I separate the whole number and the decimal to display them on the osd? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 03, 2011 10:30 am |
|
|
Use the sprintf() function. It converts the floating point number into
separate ASCII digits in an array. You can then take each digit from
the array and display it. |
|
|
pic_micro
Joined: 07 Feb 2011 Posts: 26
|
seperate ADC and display it in MAX7456 |
Posted: Wed May 04, 2011 7:55 am |
|
|
I couldn't the way describe per PCM. So I use my own way
Code: | volt = (n/1023) * 5;
d = volt * 100;
a = d / 100;
b = (d % 100)/10;
c = (d % 100)%10;
|
to seperate
the ADC result (n) and display it onto MAX7456 screen, but some how
if the ADC is max (1023) it displays 5.00V, if ADC is less than 1023 then it only display 0.00V on screen. Either my formula is wrong or my variable are wrong, I have tried my variable as long, float, char, int and nothing help.
Here are my code:
main.c
Code: | #include <16f877.h>
#device ADC=10
#fuses XT, NOWDT, NOPROTECT, NOBROWNOUT, NOPUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include <driver.c>
int thousand = 0, hundred = 0, ten = 0, one = 0;
long a, b, c, d;
float volt;
long n;
void main(void)
{
max7456_init();
enable();
setup_port_a(AN0);
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
delay_ms(1);
n = Read_ADC();
delay_ms(1);
volt = (n/1023) * 5;
d = volt * 100;
a = d / 100;
b = (d % 100)/10;
c = (d % 100)%10;
if(a == 0 )
{
a = 0x0A; //max7456 RAM location of character '0'
}
if(b == 0 )
{
b = 0x0A;
}
if(c == 0 )
{
c = 0x0A;
}
max7456_write(0x06, y+8);
max7456_write(0x07, a);
max7456_write(0x06, y+9);
max7456_write(0x07, 0x41); // decimal point "."
max7456_write(0x06, y+10);
max7456_write(0x07, b);
max7456_write(0x06, y+11);
max7456_write(0x07, c);
max7456_write(0x06, y+12);
max7456_write(0x07, 0x20); // Character "V"
}
} |
driver.c
Code: | #define MAX7456_CS PIN_A1
#define MAX7456_CLK PIN_C3
#define MAX7456_DI PIN_C5
#define MAX7456_DO PIN_C4
char x = 40;
char y = 190;
char z = 220;
char j = 83;
void max7456_write(int8 addr, int8 data)
{
output_low(MAX7456_CS);
spi_write(addr);
spi_write(data);
output_high(MAX7456_CS);
delay_ms(1);
}
//============= Disable ========================
void Disable(void) // Disable
{
max7456_write(0x00, 0x00);
}
//============= Enable =======================
void Enable(void)
{
max7456_write(0x00, 0x08); // Enable NTSC
max7456_write(0x04, 0x40);
}
//============= Enable =======================
void max7456_init(void)
{
short int i;
output_low(MAX7456_DI);
output_low(MAX7456_CLK);
output_high(MAX7456_CS);
i=input(MAX7456_DO);
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);
}
void lines(void)
{
enable();
// =========LINE1 ============
x = 1;
max7456_write(0x06, x);
max7456_write(0x07, 0x01);
delay_ms(10);
// =========LINE2 ============
x = 31;
max7456_write(0x06, x);
max7456_write(0x07, 0x02);
delay_ms(10);
// =========LINE3 ============
x = 61;
max7456_write(0x06, x);
max7456_write(0x07, 0x03);
delay_ms(10);
// =========LINE4 ============
x = 91;
max7456_write(0x06, x);
max7456_write(0x07, 0x04);
delay_ms(10);
// =========LINE5 ============
x = 121;
max7456_write(0x06, x);
max7456_write(0x07, 0x05);
delay_ms(10);
// =========LINE6 ============
x = 151;
max7456_write(0x06, x);
max7456_write(0x07, 0x06);
delay_ms(10);
}
|
Can anybody tell me what cause problem in the code? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 04, 2011 12:39 pm |
|
|
There are many problems.
In your init code below, you took out the delay (typical 50 ms) which
the MAX7456 data sheet says must be in there.
Quote: |
void max7456_init(void)
{
short int i;
output_low(MAX7456_DI);
output_low(MAX7456_CLK);
output_high(MAX7456_CS);
i=input(MAX7456_DO);
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);
// Missing the power-up delay line, here !!!
} |
In addition to that, you have 4 lines of code to setup the i/o pin direction
and initialize the levels. But I suggest that you compile a little test
program just like this (below) and look at the .LST file:
Code: |
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
//===========================
void main()
{
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);
while(1);
} |
Here's the .LST file with comments added. It's setting the correct TRIS
for you. The initial output levels are set by the SPI module itself.
So all the setup lines that you're doing are unnecessary.
Code: |
......... setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);
000F: BCF STATUS.RP0
0010: BCF SSPCON.SSPEN
0011: BCF @TRIS_C.5 // Set pin C5 (SDO) as an output
0012: MOVF @TRIS_C,W
0013: BSF STATUS.RP0
0014: MOVWF TRISC
0015: BCF STATUS.RP0
0016: BSF @TRIS_C.4 // Set pin C4 (SDI) as an input
0017: MOVF @TRIS_C,W
0018: BSF STATUS.RP0
0019: MOVWF TRISC
001A: BCF STATUS.RP0
001B: BCF @TRIS_C.3 // Set pin C3 (SCLK) as an output
001C: MOVF @TRIS_C,W
001D: BSF STATUS.RP0
001E: MOVWF TRISC
001F: MOVLW 31
0020: BCF STATUS.RP0
0021: MOVWF SSPCON
0022: MOVLW 40
0023: BSF STATUS.RP0
0024: MOVWF SSPSTAT
.................... |
There is another problem right here (in bold) with your spi setup line.
Quote: | setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16); |
Here are the #define statements that you should be using. They show
that you have specified SPI Mode 2.
Code: | #define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H) |
There is a problem with that. It's the wrong mode. Look at Figure 14 on
page 21 of the MAX7456 data sheet:
http://datasheets.maxim-ic.com/en/ds/MAX7456.pdf
It shows that SCLK idles at a low level, and that it samples the data on
the rising edge. Then go to any website that has diagrams of SPI modes
such as this one:
http://www.totalphase.com/support/kb/10045/#modes
And you can see clearly that this is Mode 0. You can see that Mode 2,
which you specified is the total opposite of the correct mode. Your setup
line should look like this:
Quote: |
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16); |
Next, you have enabled external interrupts but you don't have an #int_ext
routine. Because of this, if you get an edge on the INT pin, your program
will crash.
Quote: | enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL); |
There are some other minor problems, but I'm going to skip them for now.
I think your main problem is in the program design. If you look at various
CCS sample driver files, you'll notice that they always try to make a
character-based output routine. For example, in their LCD drivers
(whether for a character or segmented LCD), they always make an
lcd_putc() routine. There is a reason for this. CCS has special features
for string handling, such that once you have a character-based output
routine for your device, you basically have the "keys to the kingdom".
You can now use the special redirection feature of printf. Printf will format
your variable in whatever way you want, and then send it, one character
at a time, to your device output routine.
So I think the key to get your program working, is to make a character-
based output routine. Write a routine that will display one character
on the screen. It receives the character as a parameter. You can call
the routine "osd_putc()" or "max7456_putc()". If you do that, I think
most of your problems will go away. |
|
|
pic_micro
Joined: 07 Feb 2011 Posts: 26
|
|
Posted: Wed May 04, 2011 2:09 pm |
|
|
The SPI_MODE_0 always error for me. So I decide to use the SPI_H_TO_L
instead and I can display the text on the screen ok.
Quote: | Executing: "C:\CCS_PIC\PCM\PICC\Ccsc.exe" "main2.c" +FM +DF +LN +T -A +M +Z +Y=9 +EA
*** Error 12 "C:\chai\CProjects\PICC Experiment\CCS\7seg\driver.c" Line 42(35,45): Undefined identifier SPI_MODE_0
1 Errors, 0 Warnings.
Halting build on first failure as requested.
BUILD FAILED: Wed May 04 15:45:27 2011 |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 04, 2011 3:05 pm |
|
|
You have to put those #define statements for the SPI modes above main().
The compiler must see the definitions before it can use them. |
|
|
|
|
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
|