Author Topic: C Programming for 8051: SFR directions as arguments  (Read 9994 times)

0 Members and 1 Guest are viewing this topic.

Offline BRetonDPTopic starter

  • Contributor
  • Posts: 26
C Programming for 8051: SFR directions as arguments
« on: July 17, 2014, 05:03:09 am »
Hello, EEVB Community!

I'm currently making a very simple Tic-Tac-Toe game with an AT89C51RC2 and I am having issues getting the button input right.

Basically, the input is a 3x3 Button Matrix which I want to utilize by scanning through the rows with a pulse while checking the columns for a connection; pretty basic. However, the way I wanted to do this was by making a unique scroll method that received the row parameter and set it to HIGH accordingly.

I already have

sbit R1 = P1^0;

all through the needed inputs, but I'm not sure if this is correct.

Then, on my main method, I run something like

while(TRUE)
{
           scroll(R1);
}

which is named scroll, I have this

void scroll (bit P)
{
   P = HIGH;                  //Sets the row being checked to HIGH (HIGH is already defined as a 1). Same goes with the aformentioned TRUE
       ....
}

So, this is not working. I know I'm not doing this right, but I had to start somewhere. Is what I am attempting to do possible? Sending a single Pin adress as an overload for a method? If so, what datatype should it be? I was juggling between char and bit but I can't settle.

I hope my question is understandable! If not, I will gladly elaborate and maybe post all the code (although it is quite messy). Thanks, everyone, in advance!
« Last Edit: July 17, 2014, 06:39:30 am by BRetonDP »
 

Offline jav

  • Contributor
  • Posts: 37
Re: C Programming for 8051: SFR directions as arguments
« Reply #1 on: July 17, 2014, 02:41:48 pm »
Keep in mind that in C, arguments are passed by value, not by reference, so in P you get the current value of pin 0 of P1 when scroll function was called, but modifications of P won't affect R1.

You have two limitations here:
1.- You cannot define bit pointers, that will allow you to pass the value by reference.
2.- SFRs in the 8051 architecture cannot be accessed through indirect addressing, so pointers are of no use.

You can either use R1 directly in scroll function (instead of P) or change multiple bits at a time working directly over P1.
 

Offline BRetonDPTopic starter

  • Contributor
  • Posts: 26
Re: C Programming for 8051: SFR directions as arguments
« Reply #2 on: July 17, 2014, 07:51:26 pm »
You seem to have understood my problem perfectly. Thank you very much for answering. Effectively, the changes made to P wouldn't affect R1 at all...

In other forums, I have been suggested to use pointers, but that didn't seem to compile. I got an error that said invalid ptr to bit or something like that. I don't understand pointers all that well, I will study them further. Someone else suggested my scroll method look something like:

Code: [Select]
void scroll (sbit P) {...}
That is, to receive an sbit as parameter. Is this possible? I could try it out, but actually, I want to send another parameter, say, a char named R, so my method would be:

Code: [Select]
void scroll (sbit P, char R) {...}
That doesn't compile, and I'm not sure if it's because of the sbit as parameter or because of the other parameter.

In the end, I stopped trying to send the adress and have the scroll method only check my columns while I turn R1, R2 and R3 manually in my main code. Out of curiosity, what do you mean with change multiple bits at a time working directly over P1?

EDIT1 — It has been pointed out to me that sbit cannot be used as a parameter or within functions.
« Last Edit: July 17, 2014, 08:40:51 pm by BRetonDP »
 

Offline jav

  • Contributor
  • Posts: 37
Re: C Programming for 8051: SFR directions as arguments
« Reply #3 on: July 17, 2014, 09:12:33 pm »
As I said in my previous post, bit pointers aren't supported, so you cannnot do:
Code: [Select]
void scroll (bit * P) {...}
What I meant is that if you're just flipping R1, R2 and R3, and those are located in bits 0, 1 and 2 of P1 you can do things like:
Code: [Select]
R1 = 1; // Turn on R1
P1 ^= 3; // Turn off R1 and on R2
P1 ^= 6; // Turn off R2 and on R3
P1 ^= 5; // Turn off R3 and on R1

If you know the values of the other bits (pins) of P1, you can even do a direct value assignment instead of doing logical operations on the port.
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8550
  • Country: us
    • SiliconValleyGarage
Re: C Programming for 8051: SFR directions as arguments
« Reply #4 on: July 17, 2014, 09:24:22 pm »
What the hell is anyone smoking these days ? ( i jast was ranting in another topic about some 8051 code about crap programmers not understanding the machine they work on and producing crap code. so sorry if i'm being rude. i'm still fuming from that topic... )

The IO SFR's in an 8051 are bit addressable.

0x80 is pin 0 , 0x81 is pin 1 , 0x82 is pin 3 and so on  (depending on what io port the base address may be different. look it up for your port)

So simply pass the number of the pin to the routine.

do a CLRB of number +0x79 and a SETB of number 0x80

number is 1 based. so pin 1.0 is '1' pin 1.1 is '2'  otherwise the trick with CLRB 0x79 doesn't work
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: C Programming for 8051: SFR directions as arguments
« Reply #5 on: July 18, 2014, 02:52:40 am »
Pointers to bit fields are a no go.

a more generic solution to your problem is to use a pointer to the port plus a mask.

btw, scanning a keypad is quite inefficient. A faster approach is to set the row or column and read the column or row. It takes two reads.
================================
https://dannyelectronics.wordpress.com/
 

Offline jav

  • Contributor
  • Posts: 37
Re: C Programming for 8051: SFR directions as arguments
« Reply #6 on: July 18, 2014, 07:15:07 am »
do a CLRB of number +0x79 and a SETB of number 0x80

number is 1 based. so pin 1.0 is '1' pin 1.1 is '2'  otherwise the trick with CLRB 0x79 doesn't work
Unfortunately the CLRB instruction doesn't take indirect addressing, so you'd need to use a switch statement or something similar, and end up doing
Code: [Select]
R1 = 0; // CLRB
R2 = 1; // SETB
anyway.
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8550
  • Country: us
    • SiliconValleyGarage
Re: C Programming for 8051: SFR directions as arguments
« Reply #7 on: July 18, 2014, 03:02:40 pm »
then don;t use setb (it;s been a while on 8051) but you can load the accumulator with the register you want and then simply write to that location. if you point at the single bit register (that is what the 8051 does. it creates single bit registers in the SFR space that have their own address)

it is possible. i have done it. i would have to look it up. don't ask me how to do it in C. 8051 cores are not built for 'c' ( no microcontroller core is built for 'c' , c requires a stack heavy machine. ). Use Pl/M on a 8051. that language was designed from the get go for such controllers.
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #8 on: July 18, 2014, 04:04:14 pm »
no microcontroller core is built for 'c' , c requires a stack heavy machine.
eh?

From ARM's app note on migrating from 8051 to Cortex: "Unlike many microcontrollers, the Cortex-M3 can be programmed entirely in C. This includes exception handling, reset and initialization as well as application software." link
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8550
  • Country: us
    • SiliconValleyGarage
Re: C Programming for 8051: SFR directions as arguments
« Reply #9 on: July 18, 2014, 04:17:07 pm »
yeah , the cortex is the first machine to do it.
all old 8 bitters aren't. C is a language that was designerd for the digital PDP family of machines where a huge memorypool was available and with a unique architecture.
microcontrollers don't have this. 'C' wants to creat a stack, a heap and passes all stuff to routines by pushing/popping the stack.
good luck on a machine with a 16 level stack... you end up with extremele inefficient code full of workarounds becasue the architecture of the c runtime doesn't fit the hardware.

say's right there  "UNLIKE many microcontrollers."
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3339
  • Country: gb
Re: C Programming for 8051: SFR directions as arguments
« Reply #10 on: July 18, 2014, 11:08:04 pm »
yeah , the cortex is the first machine to do it.
all old 8 bitters aren't. C is a language that was designerd for the digital PDP family of machines where a huge memorypool was available and with a unique architecture.
microcontrollers don't have this. 'C' wants to creat a stack, a heap and passes all stuff to routines by pushing/popping the stack.
good luck on a machine with a 16 level stack... you end up with extremele inefficient code full of workarounds becasue the architecture of the c runtime doesn't fit the hardware.

say's right there  "UNLIKE many microcontrollers."

'C' doesn't want to create a heap unless you tell it to.  Very few projects I have worked on implement a heap since dynamic memory allocation is unnecessary for many real time applications.

C compilers also don't have to pass parameters via the stack.  How do you think C compilers for the low/mid end PICs manage, since that has no accessible stack?  The code generation on these compilers can be excellent as well.
« Last Edit: July 18, 2014, 11:09:39 pm by mikerj »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4316
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #11 on: July 20, 2014, 08:36:59 am »
Quote
C is a language that was designerd for the digital PDP family of machines where a huge memorypool was available and with a unique architecture.
Let's not get carried away; the PDP11 was a 16bit machine with a 64kbyte address space and 8 registers.   Memory and speed-wise, a modern 8051 should be on-par with an early PDP11 or LSI11.  While many regard the PDP11 architecture as particularly elegant, vendors have been claiming their chips had "pdp-11-like architectures" since the 6800 and 6502.  Usually that means at least one "index register" capable of accessing the full address space, some addressing modes useful for accessing frames via the index register, and some aids to implementing stacks.  (I'd have to check carefully to remember whether the PDP11 had explicit stack instructions, or whether they just 'fell out' of having the PC be accessible as a register, and the "standard" addressing modes.)
The 8051 is not particularly C-friendly, and the 8bit PICs are pretty awful (non-contiguous data memory; ouch!) (although, it might be interesting to see how the added PIC18 instructions really DO help C), but a lot of early 8-bit machines were better - there were credible C compilers for Z80/8080-class machines as early as the late 70s, for example.  AVRs are moderately C-friendly, despite some obnoxious departures from PDP11 styles...

ARM Cortex M cpus may be programmable in "pure" C, but that as more to do with startup and exception handling than instruction set architectures.  Excepting (small amounts of) startup and exceptions, many architectures are programmable "directly in C."  Note that the ARM does NOT have a stack-based "call" or "return" instruction, for example (which follows pretty directly from the whole RISC architecture philosophy, I think.  Can't have instructions writing memory (the stack) AND a register (two registers! SP, and PC) in the same instructions, can we?)

As for the original question, free_electron's post on the SFR registers being bit-addressable seems like the most useful approach.  You'll have to check on how your particular C compiler wants to deal with such things, though.
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #12 on: July 20, 2014, 08:49:12 am »
One thing the older servers could do, is deal with many users at the same time. Sure processing power has increased, but those VAX 8600 monsters and even the smaller 780 could deal with a lot of users at the same time.

Never got my hands on a PDP-11 but it could handle 8 users easily (of course each user running only one process).

The architecture is not quite the same I think.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4316
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #13 on: July 20, 2014, 09:01:37 pm »
Quote
the older servers could ... deal with many users at the same time.
a PDP-11 ... could handle 8 users easily
First of all, PDP11s came in a lot of different sizes, from the single-chip T-11 (http://simh.trailing-edge.com/semi/t11.html ) to large multi-user machines like the PDP11/70 that occupied several racks of space.  The multi-user machines tended to get their abilities by virtue of having complex Memory management units and intelligent peripherals, so that (for example) you could map and swap a user's memory to disk without much CPU intervention.  And by the reduced expectations of the day: I worked on PDP-10s early in my career, and while they were considered ~100 user machines, you're talking text-based apps and multi-minute compilation of student-sized programs for "normal" behavior.

The MMU and IO controllers were approximately as complex (and physically large) as the CPU itself (and "memory controllers" were fancy, too.  Not so different than modern memory (multi-word burst access for preloading the cache, and such), but less "hidden" and occupying obvious physical space.)

Microcontrollers tend to lack "memory management" capabilities, making it harder to implement multi-user systems easily or "safely", but they do have the performance.  I've implemented ~10 user systems on 10MHz 80186 or 68000 systems with 512k of memory, for somewhat limited definitions of "user"  (small internet "terminal servers"; each user gets a command processor and the ability to make network connections.)
 

Online IanB

  • Super Contributor
  • ***
  • Posts: 12420
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #14 on: July 20, 2014, 10:41:10 pm »
The MMU and IO controllers were approximately as complex (and physically large) as the CPU itself (and "memory controllers" were fancy, too.  Not so different than modern memory (multi-word burst access for preloading the cache, and such), but less "hidden" and occupying obvious physical space.)

This is very true, especially with I/O. Where dozens of terminals were connected to a DEC-10, all of those key presses were not interrupting the main CPU, and the main CPU was not doing routine keyboard processing. There were I/O front-ends and I/O multiplexers doing all the low level grunt work, leaving the main CPU to run programs.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4316
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #15 on: July 21, 2014, 07:58:33 am »
Yeah; ttys were connected to a PDP-10 via a PDP11 or PDP-8 front end (or later, via the network.)  I'm not exactly sure what sort of offload that provided, since the OS and applications would frequently use single-character IO.  It probably helped a lot on output, though.  (and again: expectations.  The "fast local terminals" on my college PDP10 ran at 2400bps, and most of the dialups were 300bps.)
Trying to analyze performance of a CPU with complicated IO controllers is ... complicated.  I actually made a bunch of "improvements" in those areas, but it was a lot of "decrease the number of context switches between user and kernel mode" and "prevent the networking code from flushing the pager cache if both packet and buffer memory were in kernel space", which were pretty impossible to measure (or so I thought at the time.)
 

Offline MarkL

  • Supporter
  • ****
  • Posts: 2239
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #16 on: July 21, 2014, 08:07:29 pm »
then don;t use setb (it;s been a while on 8051) but you can load the accumulator with the register you want and then simply write to that location. if you point at the single bit register (that is what the 8051 does. it creates single bit registers in the SFR space that have their own address)

it is possible. i have done it. i would have to look it up. don't ask me how to do it in C. 8051 cores are not built for 'c' ( no microcontroller core is built for 'c' , c requires a stack heavy machine. ). Use Pl/M on a 8051. that language was designed from the get go for such controllers.
Ok, I won't ask how in C, but how did you do this indirect bit set/clr in 8051 assembler?  (Code snippet please...)

The 8051 does not support indirect or indexed access to the SFR address space, where the port bits live.

Neither is there mapping of individual bits to full 8-bit registers in the SFR space.  There are processors, like the ARM Cortex-M3, that have individual bit mapping (their term: "bit-banding"), but the standard 8051 does not unless it's in some specific manufacturer's variant.

I've had to do something similar on an 8051 and ended up with a big 'ol switch statement, as jav states.  If there's a trick here I'd like to know.
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: C Programming for 8051: SFR directions as arguments
« Reply #17 on: July 22, 2014, 12:37:02 am »
Ok, I won't ask how in C, but how did you do this indirect bit set/clr in 8051 assembler?  (Code snippet please...)

With the Keil compiler, simply declare a variable as a type sbit, which means it's a bit-addressable SFR, and access it with the usual assignment instructions. For example, the 8051's I/O ports are bit-addressable SFRs. Declare the pin as such:

Code: [Select]
sbit PIN_SCLK = P3^0;
and the compiler "knows" how to turn assignments to/from it into setb/clr instructions:

Code: [Select]
// toggle the shift clock:
PIN_SCLK = 1;
PIN_SCLK = 0;

compiles to:
Code: [Select]
SETB PIN_SCLK
CLR PIN_SCLK

Quote
Neither is there mapping of individual bits to full 8-bit registers in the SFR space.

Now here is a clever trick. Say you need an 8-bit shift register (you're going to bit-bang something). Declare a variable in the bdata space:

Code: [Select]
static unsigned char bdata shiftreg;
and the compiler will put that variable in the 128 bytes of bit-addressable memory.

Now, declare a variable that's the MSb of that shift register:

Code: [Select]
sbit outbit = shiftreg^7;
sbit PIN_SDATA = P3^1;
;

Essentially outbit is an alias of shiftreg[7]. Now when you do the shift:

Code: [Select]
shiftreg <<= 1;
the bit you want to drive on the output now gets put into outbit automagically. The assignment:

Code: [Select]
PIN_SDATA = outbit;
compiles into two instructions. The processor can't do a move from the bdata space to a port pin directly, so the compiler goes through the carry bit:

Code: [Select]
MOV C, outbit
MOV PIN_SDATA, C

and it's reasonably clever and also obvious.

Hope this helps.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: C Programming for 8051: SFR directions as arguments
« Reply #18 on: July 22, 2014, 01:01:05 am »
The sbit approach is what the op has been using. But the question is to pass it as ab argument to a call.
================================
https://dannyelectronics.wordpress.com/
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4316
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #19 on: July 28, 2014, 12:41:26 am »
Quote
The 8051 does not support indirect or indexed access to the SFR address space, where the port bits live.
People have been saying this for quite a while, but it took some reading of the datasheet and assorted tutorials for me to realize just how ANNOYING this is!  Both in this example, and for 8051 code in general.  Hmmph.  (Is there a standard mechanism for implementing "variable ports" on 8051 that is better than a case statement?  Makes me miss the various "XCT" instructions that mainframe CPUs had for executing an instruction "out of sequence.")

It does mean that the code here is particularly poorly-suited to an 8051 architecture:
Code: [Select]
void scroll (bit P)
{
   P = HIGH;                  //Sets the row being checked to HIGH
       ....
}
In fact, passing "bit identifiers" around is not a very good idea on MOST microcontroller architectures.  (Arduino does it.  At great expense, and with much criticism.)  Your code will work much better if you pass around a bitmask for an assumed port"
Code: [Select]
void scroll (uint8_t mask)
{
   P1 = mask;                  //Sets the row being checked to HIGH
       ....
}
8051 IO ports are open-collector, with bits set to "1" essentially being inputs, right?  So perhaps your mask should have an single 0 bit shifting along, rather than a 1 bit?
 

Online IanB

  • Super Contributor
  • ***
  • Posts: 12420
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #20 on: July 28, 2014, 12:55:53 am »
I have only weakly been following this argument, since I have never programmed the 8051.

But surely the question boils down to:

a. Do you want to arbitrarily choose a particular SFR in a function call?
b. Do you want to arbitrarily set or clear a bit in a pre-determined SFR in a function call?

In the case of (a) then it looks like a switch statement is needed. But in the case of (b), I don't see why a bit number can't be passed as a function argument?

(It should be possible to read the whole register, change one or more bit states, then write it back again?)
 

Offline MarkL

  • Supporter
  • ****
  • Posts: 2239
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #21 on: July 29, 2014, 11:25:51 pm »
My use case for arbitrary SFR and bit setting is that I have a debugging CLI that I port from processor to processor for new projects.  Among other things, it allows me to read/write any memory location or I/O port, and also set/clear/watch any bit or set of bits in either of those domains.  It's very handy for new hardware exploration, development, and verification.

This code doesn't make it into any final products, and so I would agree you don't generally need pointers to SFRs or I/O port bits.

My implementation was big switch statements.   The size of the code wasn't important for that stage of development.

I make it a point to know my processor and compiler in as much detail as possible before embarking on a new development effort.  When free electron posted in #7 he had done indirect access to SFRs, I was intrigued since I didn't think it was possible.  I had looked into it a fair amount before doing it with a switch.

Still would like to know how in #7, or if it was a mistake that's fine too.  Bump.
 

Online IanB

  • Super Contributor
  • ***
  • Posts: 12420
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #22 on: July 30, 2014, 03:01:35 am »
When free electron posted in #7 he had done indirect access to SFRs, I was intrigued since I didn't think it was possible.  I had looked into it a fair amount before doing it with a switch.

Still would like to know how in #7, or if it was a mistake that's fine too.  Bump.

According to the data sheet, the SFRs share address space with actual memory. If you use indirect addressing you access the memory locations; if you use direct addressing you access the SFRs. So it doesn't look like you can indirectly address SFRs. If you use any indirect addressing modes you will be redirected to the parallel memory locations instead of the SFR space.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: C Programming for 8051: SFR directions as arguments
« Reply #23 on: July 30, 2014, 11:10:43 am »
Quote
Still would like to know how in #7, or if it was a mistake that's fine too.

Unless that poster can produce a piece of code that when burned to a chip can create the desired behavior, I would consider it a mistake.

The internet is full of such things that unless verified should be written off as non-sense.
================================
https://dannyelectronics.wordpress.com/
 

Offline MarkL

  • Supporter
  • ****
  • Posts: 2239
  • Country: us
Re: C Programming for 8051: SFR directions as arguments
« Reply #24 on: July 30, 2014, 02:44:27 pm »
Yes, of course.

It was a highly questionable claim.   The poster, only a few posts earlier (#4 in this thread), was complaining about other people not knowing about the processor architecture they were working on.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf