|
|
View previous topic :: View next topic |
Author |
Message |
wordizlife
Joined: 08 Mar 2012 Posts: 38 Location: Canada
|
Send received data to array |
Posted: Thu Mar 29, 2012 7:52 pm |
|
|
Hey everyone,
I am using the example code provided by ccs EX_SISR.c
Code: |
/////////////////////////////////////////////////////////////////////////
//// EX_SISR.C ////
//// ////
- Deleted -
|
+++++++++++++++++++++++++++
Code removed.
Reason: see forum Rule #10:
http://www.ccsinfo.com/forum/viewtopic.php?t=26245
- Forum Moderator
+++++++++++++++++++++++++++
I am not sure how to :
1. Put received data into an array
2. Read data on array
Here is the code that I have written so far. It display's some data on the LCD screen but they are all "giberish" symbols.
What the code does is.
1. Initialises the lcd
2. Powers on the microconroller that is transmitting data
3. Receive and display data.
Code: |
/***********************************************************/
/************************ Project 2 ************************/
/******************** OBDII Interpreter ********************/
/********** Included Files ***********/
#include <main.h>
#include "D:\Winter_2012\Project_2\Project2_LCD_Driver.c"
/********** Required Registers **********/
#byte TRISA = 0x85
/********** Required Bits **********/
#bit A5 = 0x5.5 // Used to power on ELM323
/********** Declared Variables **********/
char received;
int interrupt_flag;
int interrupt_flag2;
int i;
int j;
/********** Declared Array's **********/
int received_data[24]; //16F877A data Array
#int_rda
void serial_isr() {
int t;
buffer[next_in]=getc();
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
BYTE c;
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
void main()
{
enable_interrupts(int_rda);
#if defined(__PCD__)
enable_interrupts(intr_global);
#else
enable_interrupts(global);
#endif
interrupt_flag2 = 0;
While(interrupt_flag2 ==0)
{
LCD_init(); // Initialize LCD
set_disp_add_first_line();//set display address first line
interrupt_flag2 = 1;
}
delay_ms(5000);
TRISA = 0x00; // Set Pot D as outputs
A5 = 1; // Turns on ELM323
i = 0;
j = 0;
while(bkbhit)
{
For (i = 0; i<=24; i++)// increments i
{
received_data[i] = bgetc(); // saves received bytes to the array
}
}
For (j = 0; j<=24; j++)// increments j
{
text_string(received_data[j]);// reads characters from array and sends to lcd.
}
}
|
Also, I set my buffer size to 8.
Code: |
#define BUFFER_SIZE 8
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
|
I am not sure how this has affected anything since its purpose is unclear to me. But I am guessing the buffer_size would be the size of the element in my array (in my case 8 bits)?
Also on this note, in my main code that I just posted, will this code be putting a single bit into the received_data array or will it be placing all the bits that are in the buffer in the array?
Code: |
received_data[i] = bgetc();
|
Thanks! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Fri Mar 30, 2012 1:51 am |
|
|
No.
Buffer size, is the number of _characters_ of buffer generated.
The key to SISR, is understanding a 'circular buffer'. The buffer _is_ an array 'BUFFER_SIZE' characters long. However instead of being used as a 'linear' array, where the first character is at address '0', then the second at address '1' etc.. it is treated like a circular running track.
Think of the array numbers, as referring to segments round the track. '0' being at the start line, then '1' is the first corner, '2' the second half of this bend, 3 & 4 are the two halves of the back straight, 5 & 6, the bend at the other end of the track, and '7' the main straight coming back to the start line.
The racing event is run like a 'hare & hounds' race, but with bits of paper left in each segment of the track, each with a character written on them. So when a character is received, then it's bit of paper goes into part '0' of the track, and the competitor advances to part '1'. Next character received goes into '1', and the competitor advances to '2'. Where the character is going to go, is the 'next_in' value. This is the 'hare'.
The second competitor (the hound), then starts 'chasing' the first, picking up the bits of paper as they go. So they pick up the piece of paper in section '0' of the track, and advance to section 1. This is the 'next_out' counter. If 'next_out' matches the value in 'next_in', then the hare has caught up, and no more characters are waiting to be read. Key difference to the linear array is the way the two addresses 'chase' each other round the circuit. If you get to the start line (end of sector '7'), then the next part of the circuit, is sector '0' again.
Now if the hound catches the hare, this is 'buffer empty', no more characters waiting. All the bits of paper have been picked up. If the hare catches the hound, this is 'buffer full'. All eight locations round the 'lap', have pieces of paper waiting to be picked up (there then has to be a decision what to do - common solution is to start throwing the oldest bits of paper away....).
So 'bkbhit', simply tests if the hare has caught the hound.
Now some slightly more technical comments:
CCS, handle the situation at the end of the lap - where the counters go from 7, potentially to '8' on our imaginary circuit, using '%'. The % operator, gives the _remainder_ from an integer division. So 8/8 has a remainder of '0', giving us correctly the '0' location back at the start of the lap. Problem with this is how it is calculated. The '%' operator, for a _binary multiple of 1_ (1,2,4,8,16,32,64 etc..), can be solved by a single mathematical '&' operation, so is efficient. So _provided the buffer size chosen is one of these sizes_, the code will work well. Just half a dozen machine instructions. Problem is if you choose a buffer size that is _not_ such a size. Solving (for example) 12%12, requires 113 machine instructions!. This also results in using code in the interrupt that may cause interrupts to be disabled in the main code. It is unfortunately, a case of the CCS example being 'badly written'...
The 'better' solution, is to simply use:
if (next_in==BUFFER_SIZE) next_in=0;
Which effectively says 'if runner has finished lap, start a new lap', and works whatever 'buffer size' is chosen.
Now, the data is already in an array. If you want to wait for 24 characters to arrive, then make your buffer array larger than this (say 32 characters), and test for how many characters are waiting. This is coded as:
Code: |
int num_in_buff; //need to enlarge this if buffer>128 chars
num_in_buff = next_in-next_out;
if (num_in_buff>=BUFFER_SIZE) num_in_buff=BUFFER_SIZE+num_in_buff;
|
So you could just wait till 'num_in_buff' >=24, and then display this, or output this. Currently you are going to your routine when just one character has arrived, then waiting for the remaining 23, basically throwing away the 'point' of buffering the data.
Best Wishes |
|
|
wordizlife
Joined: 08 Mar 2012 Posts: 38 Location: Canada
|
How to read received data |
Posted: Fri Mar 30, 2012 9:08 am |
|
|
Perfect thank you for that explanation, cleared up a lot of things
Once I have waited for all the expected characters to be received, how would I read the data that is in the array and for example send it to an LCD or to my pc serial port with the printf() function? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Reading array |
Posted: Sun Apr 01, 2012 7:52 am |
|
|
Ttelmah has just explained it.
He's shown you how to get your data into the array, and how to keep track of data taken out.
The two indicees "next_in" and "next_out" are doing it for you.
CCS provides samples which show you how to write to LCD and PC.
Mike |
|
|
wordizlife
Joined: 08 Mar 2012 Posts: 38 Location: Canada
|
reading array data |
Posted: Sun Apr 01, 2012 12:49 pm |
|
|
Yea sorry about that I got confused for a while there.
So using the information that Ttelmah gave my main code now looks like this but does not display anything..
What could be the source of the problem?
Code: |
/********** Included Files ***********/
#include <main.h>
#include "D:\Winter_2012\Project_2\Project2_LCD_Driver.c"
/********** Required Registers **********/
#byte TRISA = 0x85
/********** Required Bits **********/
#bit A5 = 0x5.5 // Used to power on ELM323
/********** Declared Variables **********/
char received;
int interrupt_flag;
int interrupt_flag2;
int i;
int j;
int lcd_data;
int num_in_buff;
BYTE c;
BYTE received_data;
#int_rda
void serial_isr() {
int t;
buffer[next_in]=getc();
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
void main()
{
enable_interrupts(int_rda);
#if defined(__PCD__)
enable_interrupts(intr_global);
#else
enable_interrupts(global);
#endif
interrupt_flag2 = 0;
While(interrupt_flag2 ==0)
{
LCD_init(); // Initialize LCD
set_disp_add_first_line();//set display address first line
interrupt_flag2 = 1;
}
delay_ms(5000);
TRISA = 0x00; // Set Pot D as outputs
A5 = 1; // Turns on ELM323
i = 0;
j = 0;
While(1)
{
num_in_buff = next_in-next_out;
if (next_in==BUFFER_SIZE) next_in=0;
If (num_in_buff>=8)
{
For (i = 0; i <= 8; i++)
{
received_data = buffer[i];
text_string(received_data); // sends received_data to lcd
}
}
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Sun Apr 01, 2012 1:00 pm |
|
|
You don't show your declaration for buffer. My comments about the size apply, if this is not a binary multiple.
Much better to get rid of the % throughout and use the test as already outlined.
Then your calculation won't work. The 'point' is that because of the circular nature of the buffer 'next_out', can be _less_ than 'next_in', when next_in has effectively passed the finishing line. This is why I showed how to calculate the 'num_in_buff'. I subtract the values, and then if the value has wrapped (a lap has taken place), offset the number to give the required result.
Best Wishes |
|
|
wordizlife
Joined: 08 Mar 2012 Posts: 38 Location: Canada
|
|
Posted: Sun Apr 01, 2012 1:35 pm |
|
|
Here is my buffer declaration:
Code: |
#if defined(__PCM__)
#include <16F877A.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS)
#endif
#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
|
Modified main code:
Code: |
/********** Included Files ***********/
#include <main.h>
#include "D:\Winter_2012\Project_2\Project2_LCD_Driver.c"
/********** Required Registers **********/
#byte TRISA = 0x85
/********** Required Bits **********/
#bit A5 = 0x5.5 // Used to power on ELM323
/********** Declared Variables **********/
char received;
int interrupt_flag;
int interrupt_flag2;
int i;
int j;
int lcd_data;
int num_in_buff;
BYTE c;
BYTE received_data;
#int_rda
void serial_isr() {
int t;
buffer[next_in]=getc();
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
void main()
{
enable_interrupts(int_rda);
#if defined(__PCD__)
enable_interrupts(intr_global);
#else
enable_interrupts(global);
#endif
interrupt_flag2 = 0;
While(interrupt_flag2 ==0)
{
LCD_init(); // Initialize LCD
set_disp_add_first_line();//set display address first line
interrupt_flag2 = 1;
}
delay_ms(5000);
TRISA = 0x00; // Set Pot D as outputs
A5 = 1; // Turns on ELM323
i = 0;
j = 0;
While(bkbhit)
{
num_in_buff = next_in-next_out;
if (num_in_buff>=BUFFER_SIZE) num_in_buff=BUFFER_SIZE+num_in_buff;
If (num_in_buff>=8)
{
For (i = 0; i <= 8; i++)
{
received_data = buffer[i];// reads data in array
text_string(received_data); // display data from array
}
}
}
}
|
So If I understand correctly if the size is 32 I don't need any of this code?:
Code: |
num_in_buff = next_in-next_out;
if (num_in_buff>=BUFFER_SIZE) num_in_buff=BUFFER_SIZE+num_in_buff;
|
I am not sure what size I should be setting my buffer too since the amount of data being received will vary so I just set it to a size 32 to be safe. |
|
|
wordizlife
Joined: 08 Mar 2012 Posts: 38 Location: Canada
|
|
Posted: Mon Apr 02, 2012 1:17 pm |
|
|
Using the CCS Example file as reference to get the incoming data and display it to my lcd. Here is the example file:
Code: |
printf("\r\n\Running...\r\n");
// The program will delay for 10 seconds and then display
// any data that came in during the 10 second delay
do {
delay_ms(10000);
printf("\r\nBuffered data => ");
while(bkbhit)
putc( bgetc() );
} while (TRUE);
|
My question is when say:
Quote: |
// The program will delay for 10 seconds and then display
// any data that came in during the 10 second delay
|
Does that mean that the program will display ALL of the data that was received or only one byte? I have modified this code to send data to my lcd screen without any success...
Code: |
do {
while(bkbhit)
text_string( bgetc() );
}while(TRUE);
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9240 Location: Greensville,Ontario
|
|
Posted: Mon Apr 02, 2012 2:59 pm |
|
|
...
while(bkbhit)
putc( bgetc() );
...
It displays everything.. that is sent in the 10 seconds.
While...
bkbhit is true( ie. next_in does not equal next_out)
get a buffered character(the function bgectc() and then put that character onto the local console using the function putc().
text_string( bgetc() );
I suspect you may have a problem in your coding of 'text_string' as the CCS example does work.
hth |
|
|
wordizlife
Joined: 08 Mar 2012 Posts: 38 Location: Canada
|
|
Posted: Tue Apr 03, 2012 1:56 pm |
|
|
If I test my LCD code with this for example:
Code: |
text_string("hello");
|
The header file works fine and displays hello on my LCD.
Here is my text_string function:
Code: |
void text_string(char string1)
{
LCD_RS = 1;
send_nibbles(string1);
}
void send_nibbles(int data_val)
{
set_lcd_pins(data_val&0xf0);
delay_ms(10);
set_lcd_pins((data_val&0x0f)<<4);
delay_ms(10);
}
void set_lcd_pins(int data_val)
{
if( data_val & 0x80) LCD_D7=1; else LCD_D7=0;
if( data_val & 0x40) LCD_D6=1; else LCD_D6=0;
if( data_val & 0x20) LCD_D5=1; else LCD_D5=0;
if( data_val & 0x10) LCD_D4=1; else LCD_D4=0;
pulse();
}
|
Is there anything wrong with that for this code not to work?:
Code: |
do {
while(bkbhit)
text_string( bgetc() );
}while(1);
}
|
|
|
|
|
|
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
|