• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

C18 Questions

Status
Not open for further replies.

3v0

Coop Build Coordinator
Forum Supporter
IO Port Masking in C18

In JPUG#1 Multiplexing Charlieplexed Displays masking was discussed in the context of charlieplexing. The text regarding masking is discussed in the section: setLatA(), setTrisA() on page 5.

Although the article is specific to manipulating the Junebug's charlieplexed leds it should provide a good general explaination of how masking is used in relation to IO ports.

I am open to suggestions.

3v0

EDIT: Added link to JPUG#1 as suggested by Pommie. See his (the next) post for the link to the JPUG index.
 

Triode

Active Member
Moved this from the junebug thread:

The use of the suffix bits just allows you to set/clear or test an individual bit of a variable.
Thats what I thought "bits" did. In the example on multiplexing in JPUG1 masking is used to change some bits without chaning others, is it done that way because they are changing several bits at once and want to avoid changing the non targeted ones?

and to make sure Im generalizing this properly from your example
Code:
TRISBbits.TRISB1=0; or TRISB&=0b11111101
if I wanted to set port A pin 0 to input, I would type:
Code:
TRISAbits.TRISA0 = 1;
and if I wanted to set port B pin 0 high, assuming its an output according to TRISB, i guess it would be:
Code:
PORTBbits.PORTB0 = 1;
Im totally guessing on the PORTB0 part, but thats the kind of thing I could find in one of these microchip PDFs isnt it?

(I'm just explaining this to see if i have it right)
TRISB&=0b11111101 will only shut off pin 1 or anywhere you insert a 0. and if you wanted to set some high without effecting the others you would OR it with a line of 0's where you wanted no change, and a 1 where you wanted it to definitely come out high.

so for setting port A pins 1 and 3 high would I type:
Code:
 PORTA|=0b00001010;
(corrected due to input from pommie in other thread)

[end of moved post]

In JPUG#1 Multiplexing Charlieplexed Displays masking was discussed in the context of charlieplexing. The text regarding masking is discussed in the section: setLatA(), setTrisA() on page 5.
Yeah, i remember it demonstrated a method of using those commands to turn bits on or off in a single command without effecting the ones you don't intend to change. I can use it by copying it. But i'm not sure yet what LatA refers to.
 
Last edited:

Pommie

Well-Known Member
Most Helpful Member
Triode,

LATA is short for latch A and is a way to write to the actual latch circuitry of port A. This is needed because when you set/clear a single bit, the processor reads the whole port, modifies one bit and writes it back. So if you do PORTA|=4, it will read/modify/write (RMW) portA. If a bit on port A that was previously set high is heavily loaded it may read back as a zero and result in that being unintentionally cleared. The latch register gets around this problem by keeping (and returning) a copy of the previously written value.

I'm pretty sure that is a confusing explanation. For a better one google, pic rmw problem.

Mike.
 

3v0

Coop Build Coordinator
Forum Supporter
Triode said:
Thats what I thought "bits" did. In the example on multiplexing in JPUG1 masking is used to change some bits without chaning others, is it done that way because they are changing several bits at once and want to avoid changing the non targeted ones?
Yes that and one other reason. To change which bits control the LEDs ony need to change the line.

Code:
#define LED_MASK 0xC1
You would also have to change the arrays to reflect the needed values

Code:
// LEDs on A0,A6,A7
// LED index 0 1 2 3 4 5
const byte valA[]={0x01,0x40,0x40,0x80,0x80,0x01};
const byte dirA[]={0x80,0x80,0x01,0x01,0x40,0x40};
Triode said:
Yeah, i remember it demonstrated a method of using those commands to turn bits on or off in a single command without effecting the ones you don't intend to change. I can use it by copying it. But i'm not sure yet what LatA refers to.
latA is an array of bytes. The 0th element is the value you must write to LATA to get the 0th (first) charlieplexed LED to light. dirA is an array of TRISA values. The 0th element of dirA is needed to get the first charlieplexed LED to light.

Because we are only interested in PORTA bits 0,6 and 7 we use the masking to not change the other bits (1,2,3,4,5).

3v0
 

3v0

Coop Build Coordinator
Forum Supporter
LATAbit.LATA0 sort of thing is good to use if you only need to change one bit.

To make your code more portable you might do

Code:
#define STATUS_LED  LATAbits.LATA0
#define STATUS_LED_TRIS TRISAbits.TRISA0

Then in your code write

STATUS_LED_TRIS = 0;  // for output
and
STATUS_LED = 1;          // to source a LED
 

Triode

Active Member
Thanks. I think I have enough about swithing ports high and low to get my going now.

Any good C18 tutorials on how to capture a PWM signal?

Also, at some point I'm going to have to learn about having a pic generate multiple PWM signals for motor control, I know it can be done, but all the tutorials I see on generating PWM use wait commands in a single loop that would seem to get in the way of generating other pwm signals, or doing anything else for that matter. I know a few ways of timing several loops simultaniously on PC but they dont seem to apply on a PIC.
 
Last edited:

3v0

Coop Build Coordinator
Forum Supporter
We have talked about generating multiple PWM signals here several times.

To do it in software I use a timer interrupt, 100 interrupts per period. On the 0th interrupt it turns on all outputs with a duty cycle greater than zero. For the next 99 it checks to see which if any it should turn off. On the next it turns them all back on and starts over.

100 is handy because you can express the PWM duty cycle as percents. Choose whatever number of interrupts works for you application.
 

be80be

Well-Known Member
That's funny looks like C18 would set it right when changing just a bit
with just the
Code:
          #define STATUS_LED PORTAbits.RA.0
But you have to do it this way
Code:
          #define STATUS_LED  LATAbits.LATA0
 
Last edited:

Triode

Active Member
We have talked about generating multiple PWM signals here several times.
Yes, I didn't mean to ask you to go over it all again. I typically read everything i can find on a subject then ask questions about what I don't get. I haven't tried out the existing information yet, which is why I said at some point I'm going to have to figure it out. But thanks for your explanation of method you use, it'll give me a good starting point. I'll probably come back with more questions about this later. I was just mentioning that I'm about to start working on learning that so if anyone knows of a good existing tutorial they can let me know about it.

A question about the Latch command, when you change it that way, since its directly refering to the device, not the bit that controls it (as I understand it) is the bit still updated so that if you set LATAbits.LATA0 = 1 then read the status of PORTAbits.RA.0 it will also have changed? Are there any pitfalls or discrepencies here, or does it read just fine?
 

be80be

Well-Known Member
Here you go have at the whole story in a nutshell
Depending on the device selected, there are either five
ports or three ports available. Some pins of the I/O
ports are multiplexed with an alternate function from
the peripheral features on the device. In general, when
a peripheral is enabled, that pin may not be used as a
general purpose I/O pin.
Each port has three registers for its operation. These
registers are:
• TRIS register (data direction register)
• PORT register (reads the levels on the pins of the
device)
• LAT register (output latch)
The data latch (LAT register) is useful for read-modifywrite
operations on the value that the I/O pins are
driving
PORTA is a 7-bit wide, bi-directional port. The corresponding
Data Direction register is TRISA. Setting a
TRISA bit (= 1) will make the corresponding PORTA pin
an input (i.e., put the corresponding output driver in a
Hi-Impedance mode). Clearing a TRISA bit (= 0) will
make the corresponding PORTA pin an output (i.e., put
the contents of the output latch on the selected pin).
Reading the PORTA register reads the status of the
pins, whereas writing to it will write to the port latch.
The Data Latch register (LATA) is also memory
mapped. Read-modify-write operations on the LATA
register reads and writes the latched output value for
PORTA.
 
Last edited:

3v0

Coop Build Coordinator
Forum Supporter
Now that Burt has brought it up maybe we should say a word about port bit field names.

In C18 some ports use names like
PORTXbits.RX0
while others will have names like
PORTXbits.PORTX0

If in doubt check the processor .h (ie: p18f1320.h) file to see what names are used or allowed. It helps if you understand what a union is. You can even add to or modify the definitions it you like. But I would not recommend it in most cases.
 

3v0

Coop Build Coordinator
Forum Supporter
The reason being that it makes your code less portable right?
Only in that code written to use it requires your version of the modified pxxfxxxx.h file for your code to work. For the sake of sanity do not use the original file name! It would also cause the file to be a bit harder to read because the reader would have to look to the .h file to see the nonstandard name. Neither is a big deal, but I suggest it should be done with a good reason, not because you can.

In some cases people have rewritten the entire naming convention for embedded compilers. One example is Peter Anderson custom header files that he uses with the CCS compiler.

Most of the time we use #define to provide alternate names for ports and bits.
 

Triode

Active Member
I was just wondering what other trouble it might cause. I woulden't change it, like you said there aren't many good reasons to do that instead of just using define. Keeping things standard is hard enough with all the versions of any given language we already have.
 

Triode

Active Member
Can anyone point me to a good demo or tutorial of using the timers and/or capture compare in C18? I've been trying to find examples and tutorials, but most of the code I can find is not meant to be an example, so it's got a lot of other stuff and not commented with a newb in mind.
 

be80be

Well-Known Member
Last edited:
Status
Not open for further replies.

EE World Online Articles

Loading
Top