View previous topic :: View next topic |
Author |
Message |
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
18F26K22 uart |
Posted: Fri Mar 02, 2012 2:56 pm |
|
|
The 18F26K22 has an errata on the UART that requires BRG16 = 1 and BRGH = 1. Is there a way to force the set_uart_speed to use this? I can set all of the registers manually but would like to be able to use the built in functions if possible. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 02, 2012 9:13 pm |
|
|
I don't think there is a way to do it with the built-in function. I think you
need to write your own function (with a new name) that uses the equation
given in the errata. Use #byte and #bit statements to define the
baudrate registers and the BRG16 and BRGH bits. Then write to the
registers and bits in your new function. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Mar 03, 2012 4:58 pm |
|
|
OOPS - I found it in version D of the erratum.
I did not know there were SO many problems with the silicon in this part !!!!!
I had been considering the 46k22 for its DUAL EUSARTS but now ???
Second and third thoughts come to mind and
this takes me back to the crazy B.S. surrounding 16C74 and 16c6xx UART speed limit plagues of many years ago - only this is WORSE by far.....
A 1 in 256 chance of mis-interpreting or losing characters ??
Totally unacceptable IMB.
OH - right I can work around it -- great
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
a fix for the problem |
Posted: Sun Mar 04, 2012 7:39 pm |
|
|
Code: |
// void Set_baudfix( int1 uartnum, unsigned int32 masterfreq, unsigned int32 baudrate){
void Set_baudfix( unsigned int32 masterfreq, unsigned int32 baudrate){
unsigned int16 baudiv;
// UART 1
#byte SPBRG =0xFAF
#byte SPBRGH=0xFB0
#byte TXSTA =0xFAC
#byte BAUDCON=0xFB8
#BIT BRG16 =0xFB8.3
// UART 2
#byte SPBRG2 =0xF75
#byte SPBRGH2=0xF76
#byte TXSTA2 =0xF72
#byte BAUDCON2=0xF70
#BIT BRG16_2 =0xF70.3
baudiv= (unsigned int16) (( masterfreq / (4*baudrate))-1);
BRG16=1;
SPBRG =make8(baudiv,0);
spbrgh=make8(baudiv,1);
txsta=0xA6; // std 8 bit see txsta bit mapping and BRGH=1
}
|
Sorry if it looks like Hi-Tech code but it does the trick per the UART Error issue. I used #use RS-232 as usual - and then call this function in MAIN after I intialize all the PIC I/O and onboard hardware features I will be using but before any RS-232 of course - typically JUST before I start my RS-232 interrupt receive services and have done no transmit yet .
masterfreq is the SAME value you put into your #use delay() setup.
I put the defines and a prototype header there for the SECOND UART port but am too lazy this evening to finish it off.
|
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Sun Mar 04, 2012 8:03 pm |
|
|
Using version 4.114 I just finished two projects that use both UARTS
on the 18F46K22 and had no problems running standard baud rates
from 9600 up to 115K. Mine are A4 revs from Mouser.. _________________ Google and Forum Search are some of your best tools!!!! |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
Thanks |
Posted: Tue Mar 06, 2012 8:03 am |
|
|
I had figured that I would need to set the registers directly and I do have everything working correctly with that. I was hoping there was a simple way to use the built in functions. This is a nice chip and costs less but I have A2 rev chips I am using for development and testing. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Tue Mar 06, 2012 8:32 am |
|
|
As a quick saving, why not take advantage of #word....
Code: |
// void Set_baudfix( int1 uartnum, unsigned int32 masterfreq, unsigned int32 baudrate){
void Set_baudfix( unsigned int32 masterfreq, unsigned int32 baudrate, int1 uart){
//uart = 0/1 for UART 1/2
unsigned int16 baudiv;
// UART 1
#word SPBRG =0xFAF
#byte TXSTA =0xFAC
#byte BAUDCON=0xFB8
#BIT BRG16 =0xFB8.3
// UART 2
#word SPBRG2 =0xF75
#byte TXSTA2 =0xF72
#byte BAUDCON2=0xF70
#BIT BRG16_2 =0xF70.3
bauddiv= (unsigned int16) (( masterfreq / (4*baudrate))-1);
if (uart) {
BRG16_2=1;
SPBRG2=bauddiv;
txsta2=0xa6;
}
else {
BRG16=1;
SPBRG =bauddiv;
txsta=0xA6; // std 8 bit see txsta bit mapping and BRGH=1
}
}
|
Modified to handle both UART's (0/1 for final variable).
No point in using int8 registers when the compiler can treat it as an int16.
You could generate a 'smaller' visually routine, by just using the UART address, and offsets, but the actual code would be larger and slower.
Best Wishes |
|
|
|