![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
huseinnajmi
Joined: 10 May 2007 Posts: 2 Location: Pakistan
|
PIC18F26K22, UART2 Baud Rate following UART1 |
Posted: Thu Apr 28, 2016 9:24 am |
|
|
Version of your compiler: PCWHD 4.138
Target PIC Microcontroller: PIC18F26K22
Standard Run Mode or Debug Mode. Standard
Target voltage: 5V
Target oscillator speed, type: #use delay( internal = 16.384MHz )
Code: |
#include "18F26K22.h"
#define _ _file_ _date_ _time_ _
#device adc=10
#device *=16
#FUSES INTRC //Internal RC Osc
#FUSES HFOFST //High Frequency INTRC starts clocking CPU immediately
#FUSES PLLEN //4X HW PLL enabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOWDT //No Watch Dog Timer
#FUSES CCP2C1 //CCP2 input/output multiplexed with RC1
#FUSES CCP3C6 //CCP3 input/output multiplexed with RC6
#FUSES CCP2C0 //CCP2 input/output multiplexed with RC0
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES MCLR //Master Clear pin enabled
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOCPD //No EE protection
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#use delay( internal = 16.384MHz )
#priority RDA, RDA2, TIMER1
#use rs232( BAUD = 4800, RCV=PIN_B7, XMIT=PIN_B6, ENABLE=PIN_B5, PARITY=N, BITS=8, STREAM=RS485 )
#use rs232( BAUD = 9600, RCV=PIN_C7, XMIT=PIN_C6, PARITY=N, BITS=8, STREAM=MODBUS_DEVICE )
#zero_ram
#opt 9
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#define PORTB_DIR 0b11011111
#define PORTC_DIR 0b11000000
///////////////////////////////////////////////////////////////////////////////////////////////////
void main( void )
{
set_tris_a( PORTA_DIR );
set_tris_b( PORTB_DIR );
set_tris_c( PORTC_DIR );
.
.
.
.
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
enable_interrupts( INT_TIMER1 );
enable_interrupts( INT_RDA );
enable_interrupts( INT_RDA2 );
enable_interrupts( GLOBAL );
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
while( TRUE )
{
...
...
...
}
}
|
Requirement:
I want to have BAUD 9600 @ STREAM=MODBUS_DEVICE and BAUD 4800 @ STREAM=RS485.
Using the above code I get 4800 on both.
By just changing the Stream = RS485 BAUD to 9600 I get my code to work exactly as I want, with the problem that now both the interfaces are at 9600.
H/W setup:
RS485 Stream is connected to PC and Stream MODBUS is connected to MODBUS device.
When data is received from Modbus device it is displayed on the PC. Debug data constantly is printed to PC via RS485 stream
Testing:
RS485 Stream @ 4800, PC at 4800, Modbus Stream @ 9600 - debug data ok. No Modbus data received.
RS485 Stream @ 9600, PC at 9600, Modbus Stream @ 9600 - debug data ok, Modbus data ok.
I have tested the wave forms at the MODBUS Side via a scope and they change when I change the RS 485 Stream.
Tried with opt 0 and 9 - same results. Tried using setup_uart() no luck!
Note: If it was an error of simply swapping streams, then I wouldn't need to change the baud on the PC to get it to display correct ASCII data. _________________ There is no virtue in not knowing that which can be known |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Thu Apr 28, 2016 12:01 pm |
|
|
I'm surprised you get data correctly at all.
The internal oscillator is 16MHz+/- 2%, not '16.384MHz'. This means the baud rate values will be incorrectly set, giving about 2.4% error. This is 'borderline' for RS232 to be operational....
Use the UART names. So:
Code: |
#use delay( internal = 16MHz )
#priority RDA, RDA2, TIMER1
#use rs232( BAUD = 4800, UART2, ERRORS, ENABLE=PIN_B5, PARITY=N, BITS=8, STREAM=RS485 )
#use rs232( BAUD = 9600, UART1, ERRORS, PARITY=N, BITS=8, STREAM=MODBUS_DEVICE )
|
ERRORS should _always_ be used with a hardware UART, unless you are adding your own error handling code.
You have the CCP2MX fuse both turned on and off....
The compiler will be ignoring one, but which one....
Your chip gives 16MHz without the PLL. Hopefully the compiler is overriding your enabling this.
With the RS485 stream set slower than the Modbus stream, there needs to be interrupt driven TX buffering, and gaps in the data, otherwise the PC link is never going to keep up. Since the code will have to wait to transmit.....
If it is trying to send data at 4800bps, that is arriving at 9600bps, after only a couple of characters the UART will overflow, and (without ERRORS), become permanently hung. This is why you are not seeing the Modbus data..... |
|
![](templates/subSilver/images/spacer.gif) |
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Thu Apr 28, 2016 1:03 pm |
|
|
Hi,
Yes, and then there is the fact that your compiler is quite ancient..... I don't think it would ever be worth my time to mess with such an old compiler! What are you really saving anyway?? _________________ John
If it's worth doing, it's worth doing in real hardware! |
|
![](templates/subSilver/images/spacer.gif) |
huseinnajmi
Joined: 10 May 2007 Posts: 2 Location: Pakistan
|
|
Posted: Sun May 01, 2016 11:07 am |
|
|
Thank you Ttelmah and ezflyr for your time.
Wow! So many bugs!!
MODBUS RX interrupt. The 485 is similar
Code: |
#int_RDA
void RDA_isr( void )
{
com1.data = fgetc( MODBUS_DEVICE );
if( !com1.error && !com1.data_exe )
{
com1.rx_buffer[ com1.data_count ] = com1.data;
if( ++com1.data_count > COM_BUFFER_MAX - 2 ) { com1.data_count = 0; }
com1.data_exe_time_out = RESET;
}
}
|
error handling is done in the main loop:
Code: |
while( TRUE )
{
second_tick();
com1_error_check();
com1_function();
com2_error_check();
com2_function();
restart_wdt();
}
|
The com1 error checking routine
Code: |
void com1_error_check( void )
{
int8 a;
if( OERR1 )
{
OERR1 = 0;
CREN1 = 0;
CREN1 = 1;
OERR1 = 0;
}
else if( FERR1 )
{
FERR1 = 0;
OERR1 = 0;
a = RCSTA1;
while( RC1IF )
{
a = RCREG1;
}
com1.error = 1;
}
else
{
com1.error = 0;
}
}
|
Questions:
Quote: |
The internal oscillator is 16MHz+/- 2%, not '16.384MHz'. This means the baud rate values will be incorrectly set, giving about 2.4% error. This is 'borderline' for RS232 to be operational....
|
You mean to say that 16.384MHz is not possible, since the max supported is 16MHz with an error of +/- 2%? So even though I've set 16.384 it will be 16MHz throwing the rest of the calc off. Correct?
Quote: |
ERRORS should _always_ be used with a hardware UART, unless you are adding your own error handling code. |
Pls confirm - with ERRORS the _uC_ automatically clears any errors prior to transmission? The RS232_ERRORS can be accessed a_variable = RS232_ERRORS; The CCS help is rather basic. Can you please direct me to some literature where I can get more info / understanding? Thanks.
Acknowledged on the CCP2.
Quote: |
Your chip gives 16MHz without the PLL. Hopefully the compiler is overriding your enabling this.
|
My understanding is that after all the fuses the #use delay( internal = 16.384MHz ) decides what the frequency is. i.e if PLL is enabled it will use the PLL to generate the required frequency, if PLL is disabled it will generate the frequency w/o the PLL. Kindly point to a resource where I can read up on this.
TX Buffering
The MODBUS doesnt dump to RS485. The Modbus populates internal variables which are called on the RS485. _________________ There is no virtue in not knowing that which can be known |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Sun May 01, 2016 11:33 am |
|
|
ERRORS does nothing to the transmit code.
It adds basically the same code as your error handling, to the _getc_.
If an overrun triggers, the interrupt will be called. The error handling wants to be in the INT_RDA. If an error does occur, RCSTA is copied into RS232_ERRORS. So if you test the FERR bit in this, it will give you your error indication.
Your code won't work, unless you are disabling interrupts round the error handler. If RCIF is set, the interrupt will be called, so the whole thing goes astray....
Yes, all the timings will be off. The chip generates 16MHz. You can adjust the frequency a little, but this is not a 'set it to XXX' type adjustment, but a 'tweak up/down', that has to be done relative to the tweak applied from the ROM, that is programmed at the factory to give the nominal 16MHz. The compiler loads the factory programmed tweak factor.
The data sheet. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|