|
|
View previous topic :: View next topic |
Author |
Message |
PrinceNai
Joined: 31 Oct 2016 Posts: 482 Location: Montenegro
|
18f46k22 UART problem |
Posted: Sun Feb 16, 2020 7:08 am |
|
|
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: 19592
|
|
Posted: Sun Feb 16, 2020 7:28 am |
|
|
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
|
|
Posted: Sun Feb 16, 2020 7:29 am |
|
|
Post your main(). |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 482 Location: Montenegro
|
|
Posted: Sun Feb 16, 2020 7:43 am |
|
|
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: 482 Location: Montenegro
|
|
Posted: Fri Feb 28, 2020 1:33 pm |
|
|
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: 9272 Location: Greensville,Ontario
|
|
Posted: Fri Feb 28, 2020 4:08 pm |
|
|
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: 482 Location: Montenegro
|
|
Posted: Sat Feb 29, 2020 7:10 am |
|
|
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: 19592
|
|
Posted: Sat Feb 29, 2020 9:20 am |
|
|
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. |
|
|
|
|
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
|