CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Using #int_rb for serial port

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
gopalakrishnan



Joined: 18 Jun 2010
Posts: 25

View user's profile Send private message

Using #int_rb for serial port
PostPosted: Sun Jul 25, 2010 11:52 pm     Reply with quote

Kindly explain to me what does this code do. I can't come to the conclusion. Then, why can't we use B4-B7 (#int_rb) and C4-C7 for software uart? Is there any specific reason? Shall we use A0-A5? Kindly explain.
Code:

#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);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19348

View user's profile Send private message

PostPosted: Mon Jul 26, 2010 5:06 am     Reply with quote

This is all down to hardware.

The hardware UART, has a shift register, into which a character is shifted bit by bit as it arrives. Once this register is full, the contents are transferred into a second register, the process starts again, and INT_RDA, is triggered.
The code shown, is triggered when a character of data has already arrived, and been transferred to the holding register. It then reads this character, and stores it into a software 'circular buffer'.
Key here is that the hardware has already received a character before the routine is called.

Now, you can use _one_ 'level' interrupt, and have this trigger when the first 'bit' of an incoming character arrives, then sit and simulate the shift register in software (the software UART), to receive the character. _But_ while you are doing this, nothing else can happen. So you can't use the four bits of INT_RB for four channels, since once one bit arrives of an incoming character, the code has to wait inside the interrupt handler to receive all the remaining bits, and _will_ miss any other characters that are arriving....

You can receive multiple streams using software code, by using a timer interrupt, rather than a level interrupt. However _not_ using the CCS software UART. I have in the post published here an outline of a timer based receive routine, and the same approach can also handle transmission at the same time (which the CCS software UART cannot do).

Best Wishes
gopalakrishnan



Joined: 18 Jun 2010
Posts: 25

View user's profile Send private message

regarding garbage character
PostPosted: Tue Jul 27, 2010 6:27 am     Reply with quote

I had gone through your forum replies it is so resourceful.
This is my experiment. When I transmit a string from the hardware uart, and received that string in software uart B0. Whenever the data is in the receive pin I had been interrupted by #int_ext. Inside the routine I store the received string in an buffer buffer[next_in]. Finally I send the received string to the lcd. This what my experiment is to be. I see my display blank some times I receive an garbage character.

I can able to receive an interrupt, where as I am unable to display the received string. Here is post my code. In the code kindly help me to get out of it. Thanks in advance.
Kindly clarify what to do with this code for getting a transmitted character from hardware uart to software uart. I am receiving a garbage character or undefined character in my display.
Code:

#include "D:\transinnova\temp\test\rcv_intr.h"

#include <stdlib.h>
#if defined(__PCM__)

#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use standard_io(B)
#use standard_io(D)
#endif
#byte PORTB = 0x6
//#USE RS232(BAUD=9600, XMIT=PIN_C6,RCV=PIN_C7)
//#USE RS232(BAUD=9600, RCV=PIN_B0)
//main program starts

void lcd_init();
void lcd_cmd(cmd);
void lcd_data(data);

#define CR 13
#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
char k[30]={"transinnova instuments"};
//char j[20];
int i,t;
unsigned char cmd,data,a;

#int_ext
void ext_isr(void)
{
buffer[next_in]=getc();

t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;

if(next_in==next_out)

next_in=t;
}

#define bkbhit (next_in!=next_out)
BYTE bgetc()
{
BYTE c;

while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out % BUFFER_SIZE);
return(c);
}

void main()
{
ext_int_edge(H_TO_L);
enable_interrupts(int_ext);
enable_interrupts(GLOBAL);

set_tris_b(0x00);
set_tris_d(0x00);

output_d(0x00);
output_b(0x00);
lcd_init();

for(i=0;i<=31;i++)
{
delay_ms(1000);
#USE RS232(BAUD=9600, XMIT=PIN_C6,RCV=PIN_C7)
putc(k[i]);
#USE RS232(BAUD=9600, RCV=PIN_B0)
while(bkbhit)

lcd_data(bgetc());
}

}

//end of main program

//modules
//for lcd
//initilaize lcd
void lcd_init()
{
cmd=0x38;
lcd_cmd(cmd);
delay_ms(250);
cmd=0x0E;
lcd_cmd(cmd);
delay_ms(250);
cmd=0x01;
lcd_cmd(cmd);
delay_ms(250);
cmd=0x06;
lcd_cmd(cmd);
delay_ms(250);
return;
}

void lcd_cmd(cmd)
{
output_d(cmd);
output_low(PIN_b2);//rs
output_low(PIN_b1);//read write
output_high(PIN_b3);
delay_ms(250);
output_low(PIN_b3);//enabel
return;
}

//send data
void lcd_data(data)
{
output_d(data);
output_high(PIN_b2);//rs
output_low(PIN_b1);//read write
output_high(PIN_b3);
delay_ms(250);
output_low(PIN_B3);//enable
delay_ms(250);
return;

}
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Fri Aug 06, 2010 8:56 pm     Reply with quote

First, rs232 will work on slow speeds, due timing but it will be kind of stable.
Second, first char will be missing because when you send it, then irq kicks on and then program starts collecting data:
Code:

#INT_RB
void commseth() {
BYTE next_ind = 0;
char d;
   do {
      d = fgetc(eth);
      strntempe[next_ind] = d;
      next_ind++;
      }  while (strntempe[next_ind] != 0x0D);
      strntempe[next_ind+1] = 0x0D;   
      flag_comms_eth_ready = 1;
       }

So replace first char with anything and do not process it e.g. string[0] = "#", string[1,2,3,4,5...] is going to be your capture.
Then load data into string and process the string. I have stable comms on 9600 and it works well. Problem is that when rs232 is busy then mpu can't do anything else. You need to do kind of push/pull thing to communicate between 2 UARTs.

If you need high speed and efficiency then you need to have 2 UART mpu. No other way.
_________________
Help "d" others and then you shell receive some help from "d" others.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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