|
|
View previous topic :: View next topic |
Author |
Message |
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
Can not receive RS-232 data when used I2C |
Posted: Tue Aug 20, 2013 12:42 am |
|
|
Hi all
I'm having a problems when using both Rs232(int_rda) and I2C in one project.
In my project, I receive data from PC throught RS232 port, then PIC will processing data with DS1307 data; fina,l send processed data to matrix led board.
When I reading data from DS1307, the int_rda interrrupts not work, seem it can not true data in int_rda interrupts,so that i can't receive any data.
Pls show me way to fix it, i don't used int_ssp interrupts to avoid conflict between I2C and RS232 interrutps.
Thank so much !
I used PIC18F4680, CCS C ver 5.011.
Code:
Code: |
#include <18F4680.h>
#fuses H4,PUT,NOPROTECT,NOLVP,NOWDT,NOBROWNOUT,NOPBADEN, NODEBUG
#use delay(clock=40000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7, errors) // HARD UART
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
//#priority rda
#include <font.c>
#include <matrix_control_home.c>
#include <ds1307.c>
#include <GLCD_192X64.c>
#include <graph.c>
char str_rs232[19]; // str-time:18 byte
char str_disp[19]; // str-time:18 byte
char str_time_ds1307[19]; // str_time
char str_plan[19]="000"; // str_plan
char str_std_time[19]="00:00"; // str_standard_time
char c;
unsigned int8 l;
unsigned int8 i_str=0;
unsigned int8 index=0;
unsigned int1 chk_time=0;
unsigned int1 check_reset_cpu=0;
unsigned int1 check_data_time=0;
unsigned int1 check_read_ds1307=1;
unsigned int1 dis_read_ds=0;
unsigned int16 count_timer0=0;
unsigned int8 temp=0;
#include <xoa_bufer.c>
void reset_mbi(void);
void out_byte(unsigned int8 b);
void hienthi(void );
void xoaram(void);
void save_ram2(int8 ky_tu);
void chaychu(void);
void don_chu(int8 chu,int8 irow,int16 icol);
//==============================================================================
// TIMER0
//==============================================================================
#int_timer0
void ngat_timer0(void)
{
set_timer0(62);
count_timer0++;
if( count_timer0==2)
{
//output_toggle( PIN_C2);
count_timer0=0;
check_read_ds1307=1;
}
}
//==============================================================================
#int_rda
void ngat_rs232()
{
c=getc();
switch(c)
{
case '$':
{
index=0;
}
break;
//------------------------
case '*':
{
if((str_rs232[0]=='1')&&(str_rs232[1]=='T')&&(str_rs232[2]=='I')&&(str_rs232[3]=='M')&&(str_rs232[4]=='E'))
{
index=0;
chk_time=1;
}
}
break;
//-------------------------
case '#':
{
if((chk_time==1)&&(index==18)) // chuoi time 18 ki tu
{
//disable_interrupts(int_rda);
chk_time=0;
check_data_time=1;
index=0;
output_toggle(PIN_c2);
}
if((str_rs232[0]=='1')&&(str_rs232[1]=='T')&&(str_rs232[2]=='R')&&(str_rs232[3]=='S')&&(str_rs232[4]=='T'))
{
check_reset_cpu=1;
}
}
break;
//-------------------------
default:
{
str_rs232[index]=c;
index++;
}
break;
} // end of switch
} // end of int_rda
//******************************************************************************
//******************** MAIN PROGRAM ************************************
//******************************************************************************
void main(void)
{
delay_ms(100);
set_tris_a(0);
set_tris_b(0);//
//set_tris_c(0x80);
set_tris_d(0);
set_tris_e(0);
output_high( PIN_c2);
output_high(PIN_C1);
delay_ms(50);
xoa_buffer();
reset_mbi();
xoaram();
cursor=0;
printf(save_ram2,"000@11:22:33;00:00");
hienthi();
set_timer0(62);
setup_timer_0 (RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_256);
if(read_eeprom(0)==0xff)
{
write_eeprom(0,1);
init_ds1307 (); // initial DS1307
sec = read_ds1307 (0) ;
write_ds1307 (0, sec & 0x7F); // enable oscillator (bit 7 = 0)
settime_ds1307();
}
enable_interrupts(int_timer0);
enable_interrupts(int_rda);
enable_interrupts(global);
printf(" test ");
while(1)
{
//=================================================================================
if(check_reset_cpu==1)
{
reset_cpu();
check_reset_cpu=0;
}
//=================================================================================
if(check_data_time==1)
{
check_data_time=0;
output_toggle( PIN_C2);
for(i_str=0; i_str<3; i_str++)
{
str_plan[i_str] = str_rs232[i_str];
}
for(i_str=0; i_str<4; i_str++)
{
str_std_time[i_str] = str_rs232[i_str+14];
}
}
//=================================================================================
if((check_read_ds1307==1))
{
check_read_ds1307=0;
disable_interrupts(int_timer0);
gettime_ds1307();
enable_interrupts(int_timer0);
temp = hour;
hour = ((( hour & 0xf0 )>>4)*10)+(temp & 0x0f);
temp = min;
min = ((( min & 0xf0)>>4)*10) + (temp & 0x0f);
temp = sec;
sec = ((( sec & 0xf0)>>4)*10) + (temp & 0x0f);
xoa_str_disp();
strcpy(str_disp,str_plan);
sprintf(str_time_ds1307, "@%02u:%02u:%02u;", hour,min,sec);
strcat(str_disp, str_time_ds1307);
strcat(str_disp, str_std_time);
}
xoaram();
printf(save_ram2,str_disp);
xoa_buffer();
cursor=0;
hienthi();
} // end of while
} // end of main
|
_________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Tue Aug 20, 2013 1:28 am |
|
|
You never need SSP interrupts on a master. Slave, yes.
There are some things that 'worry' me.
You have no 'bounds' checking on where you write data to the RS232 array. If the 'end of time' sequence gets missed for any reason, or an extra character is received, your buffer will overflow, and destroy data in memory. I'd suggest, making the buffer a character larger, and where you write to the buffer, have something like:
Code: |
default:
{
str_rs232[index]=c;
if (index<19) index++;
}
|
This way it'll stop incrementing, if it gets to the end of the array.
Second thing, is strings. You copy the 'time' from str_rs232, but nowhere that I can see, do you add a terminating NULL. A 'string' in C, is _not_ just a sequence of characters. It is a sequence of characters _terminated with a NULL_. Without this, anything using the sequence as a 'string', risks walking over the rest of memory.
Then you have to consider, what happens if a character arrives, at the same moment you are copying the string?. This is why it is much better to effectively always 'process' data in a separate array to the one that is receiving the data. Hence, use a circular buffer (say), and copy the received data from this into the array for processing.
Now, consider switching to using software I2C....
It won't really lose you anything, and unfortunately, your chip has some very nasty I2C hardware bugs. It is possible to bodge round most of them, but there are something like a dozen problems with the I2C hardware, some of which can leave the I2C hung....
It has problems with not initialising correctly (I had to write my own initialisation code), and you have to poll before writing to SSPBUFF, to verify that a transmission is not in progress, when doing sequential writes.
The software implementation is _much_ more reliable on these chips. Unless you need hardware (for a slave), stick with software.
Best Wishes |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Tue Aug 20, 2013 2:18 am |
|
|
Thanks u ! Ttelmah
I tested with DS1307 is run correctly, read time is OK and display true on led matrix board.
I think and done to avoid eerors ,same as you tell by the way:
+
Quote: | Then you have to consider, what happens if a character arrives, at the same moment you are copying the string? |
I have disable int_rda after finish receive one string, then processed this string, and final, enable this rda interrupts again, to receive another string come on.
+
Quote: | You copy the 'time' from str_rs232, but nowhere that I can see, do you add a terminating NULL |
I calculated and added NULL character to string, so that it length 19 byte ( 18byte+ 1 byte null).
I checked again and saw the rda interrupts receive failure data, not don't receive any data, seems it corrupts data received.
My format data to send led matrix board is:(. exp)
In which:
- 000: plan exting ( rcv from PC)
- 11:22:33: format hh:mm:ss ( time data read from DS1307)
- 44:55: format standard time (also. rcv from PC)
so that i need processing strings before send to led matrix board to display.
Thanks u so much!!! _________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Tue Aug 20, 2013 2:41 am |
|
|
You do not want to disable interrupts while 'processing' the string. Sure way of missing things. It takes a long time to access characters in an array. Typically a dozen instructions for each character. If you are 'processing', this takes even longer, and you run into losing data. This is why the buffer should be separate from the processing string. Have just a small (8 character) ring buffer, and move dataas needed from this into your processing string.
Other way, disable interrupts, and use memcpy, to copy the 'interrupt' string to a separate processing buffer, then immediately re-enable the interrupts, then process the copy. Memcpy, is written to be as fast as possible to just move a block of memory from one location to another.
I's think you are actually getting an _overrun_ when you process the data, and hence a corrupted character. I suspect if you tested RS232_ERRORS you would find OERR being flagged.
Best Wishes |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9247 Location: Greensville,Ontario
|
|
Posted: Tue Aug 20, 2013 8:59 pm |
|
|
You might consider using the interrupt available from the DS1307 as the INT_EXT source.
You program the DS1307 for a 1Hz interrupt.Be sure to add a pullup ! 3k3 works fine at 5 volts.
I've done this with the 18F46K22 for about 2 years and it easily handles both RTC and Serial at 115K200.
hth
jay |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Wed Aug 21, 2013 2:49 am |
|
|
temtronic wrote: | You might consider using the interrupt available from the DS1307 as the INT_EXT source.
You program the DS1307 for a 1Hz interrupt.Be sure to add a pullup ! 3k3 works fine at 5 volts.
I've done this with the 18F46K22 for about 2 years and it easily handles both RTC and Serial at 115K200.
hth
jay |
thanks temtronic
Can you send me a sample code of your project?
If had, pls send me to email: [email protected]
thanks u _________________ Begin Begin Begin !!! |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Wed Aug 21, 2013 7:11 pm |
|
|
Quote: | Ttelmah:
Then you have to consider, what happens if a character arrives, at the same moment you are copying the string?. This is why it is much better to effectively always 'process' data in a separate array to the one that is receiving the data. Hence, use a circular buffer (say), and copy the received data from this into the array for processing. |
Hi Ttelmah
You can give me a example code for circular buffer, work with RDA interrupts.
I found in library of 4rum but haven't a example code work with 2 modes: tx and rx ( used uart interrupts)
Thanks u. _________________ Begin Begin Begin !!! |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Wed Aug 21, 2013 7:16 pm |
|
|
if you look in your examples folder in your PICC directory, you will find a file titled ex_sisr.c which has a good example of how to use interrupt driven uart receive. I would start with that. |
|
|
|
|
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
|