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

18f46k22 UART problem

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



Joined: 31 Oct 2016
Posts: 463
Location: Montenegro

View user's profile Send private message

18f46k22 UART problem
PostPosted: Sun Feb 16, 2020 7:08 am     Reply with quote

Dear Sirs,

I'm making a test project with 18F46K22 (internal oscillator) and HC-12 serial to wireless modules. Everything is on one board, the first HC-12 is on UART1 and the second is on UART2. Both are initialized to 9600 baud, same channel, same function mode, same power. My uarts are defined like this:

Code:

#use rs232(baud=9600,parity=N,UART1,bits=8,stream = PORT1,errors)
#use rs232(baud=9600,parity=N,UART2,bits=8,stream = PORT2,errors)


My receive interrupt routines are like this:
Code:

#INT_RDA
void  RDA_isr(void)
{
   tmp=getc(PORT1);                             // get received char and thus also clear interrupt flag
   buffer[next_in]= tmp;                        // move received char to the appropriate place in buffer
   ++next_in;                                   // increment IN pointer
                                                                                                                                                                                                       
   if(next_in==BUFFER_SIZE) {                   // if we have 32, go back to 0         
      next_in=0;                           
      }//; 
}

and the second:
Code:

#INT_RDA2
void  RDA2_isr(void)
{
   tmp2=getc(PORT2);                            // get received char and thus also clear interrupt flag
 
   UART2_buffer[next_in_UART2]= tmp2;           // move received char to the appropriate place in buffer
   ++next_in_UART2;                             // increment IN pointer
   output_toggle(LED);
                                                                                                                                                                                                       
   if(next_in_UART2 == UART2_BUFFER_SIZE) {     // if we have 16, go back to 0         
      next_in_UART2 = 0;                           
      }
}


I'm sending a string over from uart1 to uart2 every second in main:

Code:

const char GAME[] = "TEST\r\n";

   while(TRUE){
      UART1_Send(GAME);
      delay_ms(1000); 

   }


My problem is that when it goes over the air, I get only the first two characters of the string in UART2_buffer, over and over. No nulls, nothing. If I connect TX from uart1 to RX of uart2 directly, everything works as expected. I have a serial-usb adapter connected, listening to the traffic. I have correct string going to the transmitter and, that is what confuses me, also the correct string coming out of the receiver and going to RX2 (that is where I listen with a terminal). It doesn't work on 3,3V, nor with 5V (here levels might be wrong). I tried different oscillator speeds, no change. Is it possible I have some kind of baud rate problem? If so, how can I detect that?

Regards,
Samo
Ttelmah



Joined: 11 Mar 2010
Posts: 19375

View user's profile Send private message

PostPosted: Sun Feb 16, 2020 7:28 am     Reply with quote

Show us the UART1_Send routine.

Two characters, sounds like the routine is returning as soon as the UART
transmit buffer goes full, rather than looping till all the data is loaded.
From a 'standing start', the UART hardware can accept two characters.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 16, 2020 7:29 am     Reply with quote

Post your main().
PrinceNai



Joined: 31 Oct 2016
Posts: 463
Location: Montenegro

View user's profile Send private message

PostPosted: Sun Feb 16, 2020 7:43 am     Reply with quote

Code:

#include <i_transmit.h>
#INCLUDE <ctype.h>
#BYTE RCSTA2 = 0xF71

//#define LED PIN_A5
#define LED PIN_B5
#define HC12_SET PIN_E0
#define HC12_SET_2 PIN_E1

// Set of AT commands. I need 4 commands:
const char AT[] = "AT\r\n";                     // Every AT command starts with "AT". Answer = "OK"
const char CHANNEL_COMMAND[] = "AT+C0";         // set channell, the module returns "COK+C0XX"
const char FU[] = "AT+FU3\r\n";                 // set function. the module returns "AT+0K" NE, "OK+FU3"
const char POWER[] = "AT+P5\r\n";               // set power level. the module returns "OK+P1"
const char VERSION[] = "AT+V\r\n";              // get version. the module returns version
const char HC12_SLEEP[] = "AT+SLEEP\r\n";       // put the module to sleep. current consumption is 22uA
const char UART_MODE[] = "AT+U8N1\r\n";
const char UART_SPEED[] = "AT+B9600\r\n";

const char GAME[] = "TEST\r\n";                // send info to receiver that the game has finished

char CHANNEL_SELECT[5];

int8 Counter = 0;
char tmp;
int8 HC12_State = 0;       // state variable
int8 HC12_Response = 0;
enum {NO_RESPONSE, OK_RESPONSE, CHANNEL_OK_RESPONSE, POWER_OK_RESPONSE, FUNCTION_OK_RESPONSE, SPEED_OK_RESPONSE};          // answers from HC_12

#define CORRECT_ANSWER 1
#define WRONG_ANSWER -1
signed int8 Response;

#define BUFFER_SIZE 16                          //create 16 byte large buffer
char buffer[BUFFER_SIZE];
int8 next_in = 0;                               //max. next_in =  BUFFER_SIZE -1 !!!!!

#define  UART2_BUFFER_SIZE 60                   //create 16 byte large buffer
char UART2_buffer[UART2_BUFFER_SIZE];
int8 next_in_UART2 = 0;                         //max. next_in =  BUFFER_SIZE -1 !!!!!
char tmp2;
int8 HC12_Receiver_Get = 0;                     // state variable

char DIP_STATE;
int8 Game_Completed_Message = 0;
int8 Send_Game_Message = 0;

// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
void UART1_Send(char *s);
void UART2_Send(char *s);
// determine channel with respect to DIP switch setting
void Determine_Channel(void){
   if(DIP_STATE == 0){
      CHANNEL_SELECT = "01\r\n";
   }
   else if(DIP_STATE == 1){
      CHANNEL_SELECT = "07\r\n";
   }
   else if(DIP_STATE == 2){
      CHANNEL_SELECT = "13\r\n";
   }
   else if(DIP_STATE == 3){
      CHANNEL_SELECT = "19\r\n";
   }
   else if(DIP_STATE == 4){
      CHANNEL_SELECT = "25\r\n";
   }
   else if(DIP_STATE == 5){
      CHANNEL_SELECT = "31\r\n";
   }
   else if(DIP_STATE == 6){
      CHANNEL_SELECT = "37\r\n";
   }
   else if(DIP_STATE == 7){
      CHANNEL_SELECT = "43\r\n";
   }
   else if(DIP_STATE == 8){
      CHANNEL_SELECT = "49\r\n";
   }
   else if(DIP_STATE == 9){
      CHANNEL_SELECT = "55\r\n";
   }
   else if(DIP_STATE == 10){
      CHANNEL_SELECT = "61\r\n";
   }
   else if(DIP_STATE == 11){
      CHANNEL_SELECT = "67\r\n";
   }
   else if(DIP_STATE == 12){
      CHANNEL_SELECT = "73\r\n";
   }
   else if(DIP_STATE == 13){
      CHANNEL_SELECT = "79\r\n";
   }
   else if(DIP_STATE == 14){
      CHANNEL_SELECT = "85\r\n";
   }
   else if(DIP_STATE == 15){
      CHANNEL_SELECT = "91\r\n";
   }
   else{
      CHANNEL_SELECT = "01\r\n";
   }

}
//-----------------------------------------------------------------------------
//------------------ Send command or data to UART1 -----------------------
void UART1_Send(char *s)                        // Send command or data string
{
   while(*s) {                                  // as long as you don't encounter NULL
      fputc(*s++, PORT1);                              // send characters to selected UART1
   }
}

//-----------------------------------------------------------------------------
//------------------ Send command or data to UART1 -----------------------
void UART2_Send(char *s)                        // Send command or data string
{
   while(*s) {                                  // as long as you don't encounter NULL
      fputc(*s++, PORT2);                              // send characters to selected UART1
   }
}

// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff


// iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
#INT_EXT
void  EXT_isr(void)
{

}

#INT_TIMER0
void  TIMER0_isr(void)
{

}


#INT_RDA2
void  RDA2_isr(void)
{
   tmp2=getc(PORT2);                            // get received char and thus also clear interrupt flag
//   if((RS232_ERRORS & 0x04)==0x04){
   if((RS232_ERRORS)){
      delay_cycles(1);
   }
 
   UART2_buffer[next_in_UART2]= tmp2;           // move received char to the appropriate place in buffer
   ++next_in_UART2;                             // increment IN pointer
   output_toggle(LED);
                                                                                                                                                                                                       
   if(next_in_UART2 == UART2_BUFFER_SIZE) {     // if we have 16, go back to 0         
      next_in_UART2 = 0;                           
      }
}

#INT_RDA
void  RDA_isr(void)
{
   tmp=getc(PORT1);                             // get received char and thus also clear interrupt flag
   buffer[next_in]= tmp;                        // move received char to the appropriate place in buffer
   ++next_in;                                   // increment IN pointer
                                                                                                                                                                                                 
   if(next_in==BUFFER_SIZE) {                   // if we have 32, go back to 0         
      next_in=0;                           
      }
}

#INT_TIMER1
void  TIMER1_isr(void)
{
   delay_cycles(1);
}

// end_i_end_i_end_i_end_i_end_i_end_i_end_i_end_i_end_i_end_i_end_i_end_i_end_


void main()
{
   output_high(LED);                            // turn off LED

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);    //cca. 200 ms overflow
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);      //65,5 ms overflow

   clear_interrupt(INT_EXT);                    // prevent external int from firing at once
   enable_interrupts(INT_EXT_H2L);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_RDA);
   enable_interrupts(INT_RDA2);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   
   DIP_STATE = input_c();
   DIP_STATE = DIP_STATE & 0b00001111;          // mask upper four bits
   delay_ms(100);
   Determine_Channel();                         // get the desired channel from DIP switches
   delay_cycles(1);
   
// init the first HC-12   
   output_low(HC12_SET);                        // put HC_12 in command mode, able to receive AT commands
   delay_ms(200);                               // wait for HC_12 to enter command mode
   
   UART1_Send(AT);                               // query module for life signs
   delay_ms(200);
   UART1_Send(AT);
   delay_ms(200);
   UART1_Send(AT);
   delay_ms(200);
   UART1_Send(AT); 
   delay_cycles(1);
   delay_ms(200);

   UART1_Send(CHANNEL_COMMAND);                  // send fixed part of the command
   UART1_Send(CHANNEL_SELECT);                   // send variable channel select part + CR + NEWLINE
   delay_cycles(1);
   delay_ms(200);
   
   UART1_Send(FU);
   delay_cycles(1);
   delay_ms(200);
   
   UART1_Send(POWER);   
   delay_cycles(1);
   output_high(HC12_SET);                       // exit command mode
   delay_ms(200);                               // wait a bit for the module to safely enter UART mode

// end first HC-12 init
// init the second one

   output_low(HC12_SET_2);
   delay_ms(200);
   UART2_Send(AT);                               // query module for life signs
   delay_ms(200);
   UART2_Send(AT);
   delay_ms(200);
   UART2_Send(AT);
   delay_ms(200);
   UART2_Send(AT); 
   delay_cycles(1);
   delay_ms(200);

   UART2_Send(CHANNEL_COMMAND);                  // send fixed part of the command
   UART2_Send(CHANNEL_SELECT);                   // send variable channel select part + CR + NEWLINE
   delay_cycles(1);
   delay_ms(200);
   
   UART2_Send(FU);
   delay_cycles(1);
   delay_ms(200);
   
   UART2_Send(POWER);   
   delay_cycles(1);
   output_high(HC12_SET_2);                     // exit command mode
   delay_ms(200);                               // wait a bit for the module to safely enter UART mode

   while(TRUE){
      UART1_Send(GAME);
      delay_ms(1000);
   }
}


h file:
Code:

#include <18f46k22.h>
#device PASS_STRINGS = IN_RAM    //copy all the strings to RAM to allow access with pointers
#device ADC=10

//#FUSES NOEXTOSC                 //External Oscillator not enabled
#FUSES PUT                      //Power Up Timer
//#FUSES LPBOR                    //Low-Power Brownout reset is enabled
//#FUSES BORV27                   //Brownout reset at 2.7V

#device ICD=TRUE
#use delay(internal=4000000)

//#pin_select U1TX = PIN_C4
//#pin_select U1RX = PIN_C5

//#use rs232(baud=9600,parity=N,xmit=PIN_C4,rcv=PIN_C5,bits=8,stream=HC-12,errors)
#use rs232(baud=9600,parity=N,UART1,bits=8,stream = PORT1,errors)
#use rs232(baud=9600,parity=N,UART2,bits=8,stream = PORT2,errors)
PrinceNai



Joined: 31 Oct 2016
Posts: 463
Location: Montenegro

View user's profile Send private message

PostPosted: Fri Feb 28, 2020 1:33 pm     Reply with quote

Dear Sirs,

Today I built a second, identical board. The same firmware loaded to both, HC-12 connected to Uart1. They are chatting without a glitch. The only thing that comes to my mind is the presence of a debugger (Pickit3) with the use of both Uarts.

Regards,
Samo
temtronic



Joined: 01 Jul 2010
Posts: 9176
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Feb 28, 2020 4:08 pm     Reply with quote

you need to compile in 'release' mode for the 'real world'. Any 'debugger' has to change fuses, adds code for 'testing' purposes.....
PrinceNai



Joined: 31 Oct 2016
Posts: 463
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 29, 2020 7:10 am     Reply with quote

Done. I only have one Pickit3 at hand, so one board is programmed in release mode (both #FUSES DEBUG and #device ICD=TRUE removed) and the second one in debug mode. Works.
Ttelmah



Joined: 11 Mar 2010
Posts: 19375

View user's profile Send private message

PostPosted: Sat Feb 29, 2020 9:20 am     Reply with quote

Read the DEV revision ID on the faulty board. There is a UART erratum that
only applies to revision A2 of the chip. Might well cause your problems.
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