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 CCS Technical Support

[HELP!!] Change UART RX/TX pin dynamically using PPS
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rsappia



Joined: 22 Dec 2010
Posts: 12

View user's profile Send private message

[HELP!!] Change UART RX/TX pin dynamically using PPS
PostPosted: Thu Dec 23, 2010 7:06 am     Reply with quote

Hello, I'm currently writing a piece of code that should be able to change the output and input pin of the UART using the PPS feature. I need to do this while the program is running. So far I have tried several things.. but I still cannot get it to work properly.
Here is a simple piece of code I wrote, could you tell me what I'm doing wrong here? This code is supposed to change the output of the UART1 between RB0 and RB15 and writes a message saying on which port UART1 is writing.

Here is the .h

Code:

#include <24FJ64GA004.h>
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOJTAG                   //JTAG disabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES ICSP1                    //ICD uses PGC1/PGD1 pins
#FUSES NOIOL1WAY                //Allows multiple reconfigurations of peripheral pins
#FUSES NOWINDIS                 //Watch Dog Timer in Window mode
#FUSES WPOSTS16                 //Watch Dog Timer PostScalar 1:32768
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES PR                       //Primary Oscillator
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES NOOSCIO                  //OSC2 is clock output
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES I2C1SELD             
#FUSES SOSC_SEC             
#FUSES WUT_DEFAULT     

#word RPOR0=0x6C0           
#word RPOR7=0x6CE         
#word RPINR18L = 0x6A4     
#bit    IOLOCK  = 0x742.6
#word   OSCCON = 0x742

#use delay(clock=20000000)
#pin_select U1TX =PIN_B15 //busco
#pin_select U1RX=PIN_B1
#use rs232(baud=4800, UART1, ERRORS) 



Main Code: infinite loop transmitting text using UART1
Code:


...

unlockIO();
           
      RPOR0 = 0x0000;
      RPOR7 = 0x0300; // UART1 TXD1 ---> RP15 RB15

lockIO();
     
     
       printf ("\n \r Now I use RB15");
       
      delay_ms(50);
     
     
unlockIO();
     
      RPOR7 = 0x0000;
      RPOR0 = 0x0003; // UART1 TXD1 ---> RP0 RB0
     
lockIO() ;
     
      delay_ms(1);
     
    printf ("\n \r Now I use RB0");




And the Lock an UnLock for OSCCON
Code:



void lockIO(){

#asm
mov OSCCON,w1   //OSCCON defined in .h
mov #0x0046, w2
mov #0x0057, w3
mov.b w2,w1          //Here!! I think this could be wrong...
mov.b w3,w1     //How should I write to a memory position using asm????
bset os, #6

#endasm
}



void unlockIO(){
#asm

mov OSCCON,w1
mov #0x0046, w2
mov #0x0057, w3
mov.b w2,w1
mov.b w3,w1
bclr 0x0742, #6

#endasm
}



I run this on Proteus and I see that both pins transmit
"\n \r Now I use RB0" and "\n \r Now I use RB15" .
I have also noticed that I'm not writing properly the OSCCON register. I have simulated this code step by step and Proteus says "Word-write to OSCCON register not supported. Use byte-write with correct enable sequence".... Does it mean that Proteus does not support this PPS feature?
I would really appreciate any kind of advice on this!!
temtronic



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

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 7:47 am     Reply with quote

What does your program do in the _real_ world? IE, a real PIC programmed with your code?

Gee...Proteus doesn't seem to work ???
I'm amazed at how many have blind faith in that 'simulator'.
I can think of 22 reasons why your 'program' failed,NONE have anything to do with the CCS C compiler for your PIC.

I'm sure there's a forum for Proteus, which is the first and best place to ask your question.

This forum is designed for programmers that burn real programs into real PICs and test/work/play in the real world.

Simulations are NOT the real thing !
rsappia



Joined: 22 Dec 2010
Posts: 12

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 8:23 am     Reply with quote

temtronic wrote:
What does your program do in the _real_ world? IE, a real PIC programmed with your code?

Gee...Proteus doesn't seem to work ???
I'm amazed at how many have blind faith in that 'simulator'.
I can think of 22 reasons why your 'program' failed,NONE have anything to do with the CCS C compiler for your PIC.

I'm sure there's a forum for Proteus, which is the first and best place to ask your question.

This forum is designed for programmers that burn real programs into real PICs and test/work/play in the real world.

Simulations are NOT the real thing !


why do you attack me?

Instead of giving a helpful answer you waste your time criticising me...

First at all, I DO burn real PIC...
Just because it didnt work well i decided to try some simulation.
I was asking for help and your reply is not helpfull at all. For sure Im not doing something well in the code... and I sure you didnt read it... so please, if you have something good to say, you are welcome.
Have a great day.


Last edited by rsappia on Thu Dec 23, 2010 9:28 am; edited 1 time in total
rsappia



Joined: 22 Dec 2010
Posts: 12

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 9:24 am     Reply with quote

I will ask in other way so no one get offended...

I guess in this part of code im not doing well..

Code:

void lockIO(){

#asm
mov OSCCON,w1   //OSCCON defined in .h
mov #0x0046, w2
mov #0x0057, w3
mov.b w2,w1          //Here!! I think this could be wrong...
mov.b w3,w1     //How should I write to a memory position using asm????
bset os, #6

#endasm
}



void unlockIO(){
#asm

mov OSCCON,w1
mov #0x0046, w2
mov #0x0057, w3
mov.b w2,w1
mov.b w3,w1
bclr 0x0742, #6

#endasm
}



How should I proceed to write a memory position using assembler senteces?

I see in microchip they use something like:

Code:

mov.b w2,[w1]        .
mov.b w3,[w1]   


but CCS does not compile if I do so...
temtronic



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

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 10:04 am     Reply with quote

My answer was not an attack on you, rather that this forum is for real PICs, and NOT a Proteus simulator forum.
Simulator's are NOT reliable and are FULL of 'hidden' problems that cannot easily be diagnosed.
I'm not surprised Proteus does not work right, never seen one yet be 100% reliable in 45 years of cutting code.


However if you have real code in a real PIC, give a short, complete version of your program that can be compiled, along with the compiler version you're using and the PIC chip/die number.
This is necessary as a newer version of the PIC might have an 'errata' that the compile version you have does not correct for.

There are lots of codecutters on this site that can help with real code inside real hardware but it's beyond the scope of all of us to peer inside Proteus to see what is screwed up this time.

With respect to your error..do you have the proper RS232 drivers on both pins connected to 2 serial ports on a PC. Have you verified that the PC will accept data correctly on both ports.
Have you tried a simple loopback program that accepts data from PC on one comport to the PIC, then have the PIC loopback that data to the other comport on the PC? This will quickly show that the PIC hardware is functioning as well as the PC software.

hth
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 10:07 am     Reply with quote

The data sheet, simply says that IOLOCK, must be cleared or set in one operation after the 46/57 sequence.
Why not just try doing this in C?.

Code:

#byte OSCCON=0x742
#bit IOLOCK=OSCCON.6

void unlock_io(void) {
   OSCCON=0x46;
   OSCCON=0x57;
   IOLOCK=0;
}   

void lock_io(void) {
   OSCCON=0x46;
   OSCCON=0x57;
   IOLOCK=1;
}   

I don't see that what they are doing, actually complies with the data sheet statement...

Best Wishes
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 10:26 am     Reply with quote

Ttelmah wrote:

I don't see that what they are doing, actually complies with the data sheet statement...

Best Wishes


As long as the C compiles to exactly the right sequence...

As for the original poster,

What PIC are you using? You need to post a short working example with your compiler version for us. it looks like you're using a 16bit PIC.

cheers,

Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 10:32 am     Reply with quote

Here: Directly from the datasheet for PIC24's...

Why don't people bother to read the datasheet?

Code:
//*************************************************************
// Unlock Registers
//*************************************************************
__builtin_write_OSCCONL(OSCCON & 0xbf) //clear the bit 6 of OSCCONL to
//unlock Pin Re-map
//******************************************************************
//This code is used when interested in inline assembly. If this code is
//used then the above two lines should not be used for unlocking.
//******************************************************************
/*
asm volatile ( "push w1 \n"
"push w2 \n"
"push w3 \n"
"mov #OSCCON, w1 \n"
"mov #0x46, w2 \n"
"mov #0x57, w3 \n"
"mov.b w2, [w1] \n"
"mov.b w3, [w1] \n"
"bclr OSCCON, #6 \n"
"pop w3 \n"
"pop w2 \n"
"pop w1”");
*/
//************************************************************
// Configure Input Functions
//************************************************************
//***************************
// Assign U1Rx To Pin RP0
//***************************
RPINR18bits.U1RXR = 0; //"0’ represents RP0
//***************************
// Assign U1CTS To Pin RP1
//***************************
RPINR18bits.U1CTSR = 1; //"1’ represents RP1
//************************************************************
// Configure Output Functions
//************************************************************
//***************************
// Assign U1Tx To Pin RP2
//***************************
RPOR1bits.RP2R = 3; //"3’ represents U1TX
//***************************
// Assign U1RTS To Pin RP3
//***************************
RPOR1bits.RP3R = 4; //"4’ represents U1RTS
//************************************************************
// Lock Registers
//************************************************************
__builtin_write_OSCCONL(OSCCON | 0x40) //set the bit 6 of OSCCONL to
//lock Pin Re-map
//******************************************************************
//This code is used when interested in inline assembly. If this code is
//used then the above two lines should not be used for unlocking.
//******************************************************************
/*
asm volatile ( "push w1 \n"
"push w2 \n"
"push w3 \n"
"mov #OSCCON, w1 \n"
"mov #0x46, w2 \n"
"mov #0x57, w3 \n"
"mov.b w2, [w1] \n"
"mov.b w3, [w1] \n"
"bset OSCCON, #6 \n"
"pop w3 \n"
"pop w2 \n"
"pop w1”;
*/

_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 11:25 am     Reply with quote

Quote:
As long as the C compiles to exactly the right sequence...

Unfortunately, it doesn't.
Code:
....................    OSCCON=0x46; 
*
024C:  MOV.B   #46,W0L
024E:  MOV.B   W0L,742
....................    OSCCON=0x57; 
0250:  MOV.B   #57,W0L
0252:  MOV.B   W0L,742
....................    IOLOCK=0; 
0254:  BCLR.B  742.6

This sequence does not write to the IOLOCK bit, as you can check e.g. with a debugger. The problem is, that OSCCON=0x57 is using two machine instructions instead of one. Curiously, CCS is using the same useless code in PCD, as I already previously mentioned in a post. PCD is intending to lock peripheral pin select registers in main startup, but it doesn't. So you can simply write to the registers without unlocking anything.

The assembly code used by rsappia has multiple errors. It's neither writing the address of OSCCON to a register nor using indirect writes, as required.


Last edited by FvM on Thu Dec 23, 2010 11:47 am; edited 1 time in total
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 11:40 am     Reply with quote

FvM wrote:
Quote:
As long as the C compiles to exactly the right sequence...

Unfortunately, it doesn't.



Yep. Why I wrote that.

When CCS first added the PIC18Fxxj11 series, the unlock sequence was wrong and I had to write my own in assembler.

Inline assembly worked fine as long as I used "ASIS" because even a simple bclr to the unlock bit had a bank set in front of it or something goofy.

So even ASM may not be exactly the ASM you think unless you check the LST file.

Cheers,

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 12:14 pm     Reply with quote

Quote:
Why don't people bother to read the datasheet?

Good question. Apparently also PCD compiler programmers at CCS don't. I missed your previous post,
because I was double checking the unlock code operation in the meantime.

Finally, referring to the original post. Although the unlock/lock code is invalid, the PPS registers are written
correctly, so the Tx pin switch should work. You can, by the way, also enable Tx output to multiple pins.

For questioned unlock/lock sequence, the below code does surely work. You don't need to save the lower work
registers, unless you are in the middle of a complex (e.g. arithmetic) compiler operation.
Code:
#asm
   mov #0x742,w1
   mov #0x46,w2
   mov #0x57,w3
   mov.b w2,[w1]
   mov.b w3,[w1]
   bset 0x742,#6
#endasm
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 1:08 pm     Reply with quote

FvM wrote:
Quote:
Why don't people bother to read the datasheet?

Good question. Apparently also PCD compiler programmers at CCS don't.


Makes ya wonder.

It's kinda like all the DC-DC switchers I've been seeing lately that are definitely not following the layout guidelines which all typically talk about LOW IMPEDANCE PATHS... and you see like 10mil lines running to the main switching Inductor or some such. Datasheets are your FRIEND. EmBRACE them. Don't reject them lest they don't tell you the important stuff you need to know. :D
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 3:25 pm     Reply with quote

Actually, they are probably just suffering from the way the data sheets disagree....
If you look at the PPS section of the reference, and compare the bit mappings used with the data sheet, they differ. The text description, also differs from the example sequence. Unfortunately, while the early Microchip data sheets were 99% 'right', the current generation, seem to be taking lessons from some other companies, and are full of errors... :-(
The one thing that hasn't been mentioned, which might well stop the lock/unlock working, for the 'dynamic' change wanted, is the first line of 12.4.5.1.
"1. Disable any fixed digital peripherals on the pins to be used."

You need to turn the UART 'off', before trying to remap.

Best Wishes
rsappia



Joined: 22 Dec 2010
Posts: 12

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 3:38 pm     Reply with quote

temtronic wrote:
My answer was not an attack on you, rather that this forum is for real PICs, and NOT a Proteus simulator forum.
Simulator's are NOT reliable and are FULL of 'hidden' problems that cannot easily be diagnosed.
I'm not surprised Proteus does not work right, never seen one yet be 100% reliable in 45 years of cutting code.


However if you have real code in a real PIC, give a short, complete version of your program that can be compiled, along with the compiler version you're using and the PIC chip/die number.
This is necessary as a newer version of the PIC might have an 'errata' that the compile version you have does not correct for.

There are lots of codecutters on this site that can help with real code inside real hardware but it's beyond the scope of all of us to peer inside Proteus to see what is screwed up this time.

With respect to your error..do you have the proper RS232 drivers on both pins connected to 2 serial ports on a PC. Have you verified that the PC will accept data correctly on both ports.
Have you tried a simple loopback program that accepts data from PC on one comport to the PIC, then have the PIC loopback that data to the other comport on the PC? This will quickly show that the PIC hardware is functioning as well as the PC software.

hth


Hi, PORT RS232 is working properly. I have tried using virtual ports and real ports with no problems at all... I think that the problem is how Im trying to access the OSCCON register.
I understand what you say about Proteus, but, I just consider this feature a very simple one. I usally simulate first in proteus an then download the code in real MCU and i have had no problem in several years of practice (till now!!!! Smile )

Quote:

The data sheet, simply says that IOLOCK, must be cleared or set in one operation after the 46/57 sequence.
Why not just try doing this in C?.

Code:

#byte OSCCON=0x742
#bit IOLOCK=OSCCON.6

void unlock_io(void) {
OSCCON=0x46;
OSCCON=0x57;
IOLOCK=0;
}

void lock_io(void) {
OSCCON=0x46;
OSCCON=0x57;
IOLOCK=1;
}

I don't see that what they are doing, actually complies with the data sheet statement...

Best Wishes


I also tryed this way, and it didnt work :(

Quote:

What PIC are you using? You need to post a short working example with your compiler version for us. it looks like you're using a 16bit PIC.

cheers,

Ben



Im using the PIC24FJ64GA004

bkamen wrote:



Here: Directly from the datasheet for PIC24's...

Why don't people bother to read the datasheet? ...



CCS does not support this assembler sintax, I also tried with this after bother myself reading the data sheet and lot of examples. What I am trying to do is something similar to what is explained in microchip's data sheet, but i know im not doing well when trying to write in OSCCON

FvM wrote:



This sequence does not write to the IOLOCK bit, as you can check e.g. with a debugger. The problem is, that OSCCON=0x57 is using two machine instructions instead of one. Curiously, CCS is using the same useless code in PCD, as I already previously mentioned in a post. PCD is intending to lock peripheral pin select registers in main startup, but it doesn't. So you can simply write to the registers without unlocking anything.

The assembly code used by rsappia has multiple errors. It's neither writing the address of OSCCON to a register nor using indirect writes, as required.



I totally agree with you... my code has multiple errors!!
So you say I could go ahead and change the PPS without doing the 46/57 steps?

FvM wrote:



PostPosted: Thu Dec 23, 2010 12:14 pm Post subject:
Quote:
Why don't people bother to read the datasheet?

Good question. Apparently also PCD compiler programmers at CCS don't. I missed your previous post,
because I was double checking the unlock code operation in the meantime.

Finally, referring to the original post. Although the unlock/lock code is invalid, the PPS registers are written
correctly, so the Tx pin switch should work. You can, by the way, also enable Tx output to multiple pins.

For questioned unlock/lock sequence, the below code does surely work. You don't need to save the lower work
registers, unless you are in the middle of a complex (e.g. arithmetic) compiler operation.
Code:
#asm
mov #0x742,w1
mov #0x46,w2
mov #0x57,w3
mov.b w2,[w1]
mov.b w3,[w1]
bset 0x742,#6
#endasm


THANKS!!!! I'll try it tomorrow @ first hour... here I see clearly how should I proceed to write in OSCCON address using the [ ].
rsappia



Joined: 22 Dec 2010
Posts: 12

View user's profile Send private message

PostPosted: Thu Dec 23, 2010 3:52 pm     Reply with quote

FvM wrote:
Quote:
Why don't people bother to read the datasheet?

Good question. Apparently also PCD compiler programmers at CCS don't. I missed your previous post,
because I was double checking the unlock code operation in the meantime.

Finally, referring to the original post. Although the unlock/lock code is invalid, the PPS registers are written
correctly, so the Tx pin switch should work. You can, by the way, also enable Tx output to multiple pins.

For questioned unlock/lock sequence, the below code does surely work. You don't need to save the lower work
registers, unless you are in the middle of a complex (e.g. arithmetic) compiler operation.
Code:
#asm
   mov #0x742,w1
   mov #0x46,w2
   mov #0x57,w3
   mov.b w2,[w1]
   mov.b w3,[w1]
   bset 0x742,#6
#endasm


This absolutely works!

Now I see OSCCON is being written Smile

The only one thing I see... is that I'm still having TX1 assigned to RB0 and RB15 :(

Isn't it enough if I do this? :

Code:


unlockIO();
           
      RPOR0 = 0x0000;
      RPOR7 = 0x0300; // UART1 TXD1 ---> RP15 RB15

lockIO();

     printf ("\n \r Now I use RB15");
       
      delay_ms(50);
     
     
unlockIO();
     
      RPOR7 = 0x0000;
      RPOR0 = 0x0003; // UART1 TXD1 ---> RP0 RB0
     
lockIO() ;
     
      delay_ms(1);
     
    printf ("\n \r Now I use RB0");
     


Doing RPOR0 = 0x0000; wouldn't make RB0/RB1 to get disconnected from UART1?...
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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