Serial Reception Issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Serial Reception Issue

Jump to solution
1,327 Views
jonathan_abbati
Contributor III

Hello my friends!

 

I am trying to set some serial communication to ultimately read data from a GPS module, but I am attempting to link two identical microcontrollers together first to ensure that I can properly send( which I have already verified via hyperterminal) and receive, which is what I am unable to do so far. I am working with the MC9S12DG128 microcontroller and my code is as follows, you will notice that I am going to be utilizing my LCD display within this communication as well. Please let me know if there is anything you see that may be the issue:

 

void output_string(int cmd);void outcmd(unsigned char command);void clear (void);void output1(int op);void LCD_init (void);int read;int test;int in; void main(void) {DDRS = 0x08;PTS = 0x00;DDRH = 0xFF; LCD_init ();SCI0BD = 0x68;SCI0CR1 = 0x00;  // CHANGE BACK TO SCI0SCI0CR2 = 0x2C;SCI0DRH = 0x00; // Ensure T8 = 0 (8-bit mode)    EnableInterrupts;//SCI0CR2_RE = 0;output_string (33); // ASCII Characters !GPS, used to request information/*output_string (71);output_string (80);output_string (83);output_string (5); // Data selection line, see chart for details *///SCI0CR2_RE = 1; while(1){      PTH = SCI0DRL;     read = SCI0SR1;    in = SCI0DRL;    output1 (in);  }  for(;;) {    _FEED_COP(); /* feeds the dog */  } /* loop forever */  /* please make sure that you never leave main */}void output_string (int cmd) {          read = SCI0SR1; // Used to clear flag which must be read to do so.      while (SCI0SR1_TDRE == 0);      SCI0DRL = cmd;      while (SCI0SR1_TC ==0);}#pragma CODE_SEG __NEAR_SEG NON_BANKED void interrupt 20 SCI_ISR (void){  //while(SCI0SR1_RDRF == 1){    PTH = SCI0SR1;     read = SCI0SR1;    in = SCI0DRL;    output1 (in);     //in++;  }#pragma CODE_SEG DEFAULTvoid outcmd(unsigned char command){  unsigned int z;  PTS = 0xF0 & command;  PORTE_BIT4 = 0;  PORTE_BIT4 = 1;  PORTE_BIT4 = 0;   PTS = 0xF0 & (command<<4);  PORTE_BIT4 = 0;  PORTE_BIT4 = 1;     PORTE_BIT4 = 0;  for(z=0;z<=6666;z++);   }void clear(void){    outcmd(0x01);  outcmd(0x02);  }void output1(int op){  unsigned int x;    PORTE_BIT7 = 1;  //while(*op)  //{   // while there is contents available       PTS = 0xF0 & op;  PORTE_BIT4 = 0;  PORTE_BIT4 = 1;  PORTE_BIT4 = 0;  for(x=0;x<=4;x++);   PTS = 0xF0 & (op<<4);  PORTE_BIT4 = 0;  PORTE_BIT4 = 1;  PORTE_BIT4 = 0;  for(x=0;x<=6666;x++);  //op ++;  //} }void LCD_init (void) {  unsigned int z;                                                 DDRS = 0xFF;DDRE = 0xFF;PORTE_BIT7 = 0;PTS = 0x00;for (z=0;z<=33333;z++); // 50ms wait specified by manufactuer to ensure LCD voltage level moves up to proper power level for (z=0;z<=33333;z++);PTS = 0x30;for (z=0;z<=6666;z++);PTS = 0x30;for (z=0;z<=213;z++);PTS = 0x30;for (z=0;z<=213;z++);PTS = 0x20;  // 4 - bit initialization PORTE_BIT4 = 0; // Toggle enable to process data PORTE_BIT4 = 1;PORTE_BIT4 = 0;for(z=0;z<=6666;z++); // 5ms delay outcmd(0x28); // 4-bit 2 line setupoutcmd(0x08); // turn display off clear(); outcmd(0x06); // entry mode set to incriment DDRAM addressoutcmd(0x0F); // Turn display/cursor/blink on}

 

 

 It seems that I am not even generating an interrupt or getting anything to be received into the SCI Data register. Thank you so very much for your time and I greatly appreciate you taking the time look at this posting!

 

Sincerely,

Jonathan

Labels (1)
0 Kudos
1 Solution
1,008 Views
jonathan_abbati
Contributor III

The code is absolutely fine, there is a jumper on board which enables / disables the RX.

View solution in original post

0 Kudos
8 Replies
1,008 Views
kef
Specialist I

I don't see in your code what could cause SCI receive interrupt to be not triggered. But since you write "seems", I want to ask what debugging tools are you using? With decent debugger It should be as simple as a brick to detect is your ISR routine called or not.

 

The very serious problem in your code is call from ISR to routine that wastes CPU power in software delay loop. You should never loop in any interrupt routine. In case of SCI interrupt, you should loose data coming to RX pin.

 

Don't use any magic numbers in your code.

 

SCI0CR2 = 0x2C; 

                  ^^^  What do these bits mean? Do you really know what are these without looking into datasheet? Isn't this better to:

 

SCI0CR2 = SCI0CR2_RIE_MASK | SCI0CR2_TE_MASK | SCI0CR2_RE_MASK;

 

Or even better, especially in the case you may need to change setup in the future easily, without looking into datasheet. Just replace 0->1 or 1->0 to set or clear bit. Compiler generated code will be the same like SCI0CR2= 0x2C;

 

SCI0CR2 =   SCI0CR2_TIE_MASK * 0            // comments

                   | SCI0CR2_TCIE_MASK * 0          //

                   |  SCI0CR2_RIE_MASK  * 1

                   |  SCI0CR2_ILIE_MASK  * 0

                   | SCI0CR2_TE_MASK   * 1

                   | SCI0CR2_RE_MASK * 1

                   | SCI0CR2_RWU_MASK * 0

                   | SCI0CR2_SBK_MASK * 0

                 ;

 

void interrupt 20 SCI_ISR (void){

                      ^^ probably you didn't know that CW headers contain all defines for interrupt vector addresses and interrupt vector numbers. I recommend replacing 20 here with VectorNumber_Vsci0.

 

0 Kudos
1,008 Views
jonathan_abbati
Contributor III

Dear Kef,

 

Thank you so much for taking your time to help out on this issue I greatly appreciate your time and effort.

 

What you have proposed in concerns to the setting of SCI0CR2 is a brilliant change to the code, for I have had to look back to the data sheet several times to ensure that I have set the correct bits within the control register.

 

With concerns to debugging, I have attempted to avoid using the interrupt all together after coming across an article published from Motorola which depicted some interrupt generation issues and simply placed the interrupt code within a infinite while loop which will simply read whatever is in SCI0DRL and place it onto my LCD. What is really puzzling at this moment is that the RDRF flag never becomes active which is rather odd. I have determined this by setting conditional loops which are based off of the setting of RDRF and checking the memory locations during transmission within Codewarriors integrated Debugger. As I mentioned earlier, I know for sure that the transmission works, but for some reason nothing is even making it into the receive shift register. Would you perhaps have any suggestions or ideas with regards to this? Once again, thank you so much for your time, I greatly appreciate it.

0 Kudos
1,008 Views
Lundin
Senior Contributor IV

Is the document you are referring to the errata of the old 'B' mask? On that old maskset, setting an odd number of interrupts would cause interrupt flag-related silicon bugs. The solution is simple: don't use that old mask, the bug has alredy been fixed long time ago.

 

If the chip on your dev board is labelled MC9S12DG128B, replace it with a new one.

0 Kudos
1,008 Views
jonathan_abbati
Contributor III

Dear Lundin,

 

You are most definitely correct with what you have shared with me. Thank you so very much for that because I was very worried that once I figured this problem out, I would not be able to use the interrupt. However, this is not the real issue at the moment, for the reception still does not work and will not set the RDRF flag for me to even implement the interrupt. Would you perhaps have any ideas as to why this flag and the SCIDRL register remain empty if I have already ensured that the transmission is working just fine? Thank you very much for your time, I greatly appreciate it.

 

Sincerely,

Jonathan

0 Kudos
1,008 Views
kef
Specialist I

Did you verify with oscilloscope that serial data reaches Rx pin?

To determine if Rx interrupt happens just set a breakpoint in SCI ISR.

Looking at SCI registers with debugger won't work reliably in your case, since while loop in your main() and SCI ISR are both clearing RDRF flag. Don't forget also that reading SCI registers with debugger may clear RDRF and other SCI flags. SCI RDRF clearing sequence consists of reading SCI status register when RDRF is set, then reading data register. Debugger may reproduce this sequence updating contents of data window, of course in the case when data window includes SCI registers...

 

0 Kudos
1,008 Views
jonathan_abbati
Contributor III

I have verified that the data is reaching the RX pin, but it not entering the shift register. I have by passed using the interrupt for simplicity and troubleshooting for now. I am sending a continuous string of data to the  microcontroller to see if I am even generating the OR flag, but that is not even happening, it is almost as if there is something with the serial reception that I am not initializing. I have the RE bit set and I do not know if there is anything else such as some sort of mode setting to ensure that PS2 is set as RXD1. Would you have any more ideas towards this my friend? Once again, thank you so very much for all of your help!

 

Sincerely,

Jonathan

0 Kudos
1,009 Views
jonathan_abbati
Contributor III

The code is absolutely fine, there is a jumper on board which enables / disables the RX.

0 Kudos
1,008 Views
jonathan_abbati
Contributor III

Thank you all so much for your help!

0 Kudos