Mapping a structure to a port.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Mapping a structure to a port.

2,336 Views
Seegoon
Contributor I
Hi to all.
I am porting some code from a PIC to a HCS12 micro. I want to use the
same lcd routines on the new micro. I seem to have it mostly figured out
but I,m not sure how to "map" the lcd structure onto the hcs12 port(Port AD I/O Register; address 0x00000270)
I'm fairly new to this sort of stuff and am a bit stuck.

Ive tried this , but it does not work. It compiles but the outputs don't work.
My lack of "C" knowledge is letting me down here I think :0(


Code:



struct lcd_pin_map

         char unused   :1;     
         char enable    :1;
         char rs           :1;               // access to the LCD pins.
         char rw          :1;
         char data       :4;                    // The bits are allocated from
};

struct lcd_pin_map lcd;

#define lcd_pin_map lcd @ (*((volatile unsigned char *)(REG_BASE + 0x00000270)))

I basically want to connect the lcd(16*2) to port AD.

If anyone has any other nice lcd routines I'm happy to try them out.

Any help appreciated.

Cheers
Rob

Labels (1)
0 Kudos
Reply
4 Replies

887 Views
Steve
NXP Employee
NXP Employee
For a comprehensive answer have a look at AN2485 which details how we built some software stationery using this kind of approach. Depending on the part you are using you may find some stationery that fits.
Placing the structure at a place in memory is dependent on the compiler but something like this will probably work:
1/ Define a type
2/ Declare a variable of that type @address
 
typedef struct

         char unused   :1;     
         char enable    :1;
         char rs           :1;               // access to the LCD pins.
         char rw          :1;
         char data       :4;                    // The bits are allocated from
} tlcd_pin_map;
 
volatile tlcd_pin_map @ (REG_BASE + 0x00000270);
0 Kudos
Reply

887 Views
Lundin
Senior Contributor IV
Some things to consider:

The bitfield struct you have written is not ISO C and may not work on ISO C compilers. Only the int type is allowed for bitfields.

Allocating two variables at the same location will never work out well. The register is already allocated at the location you want. You could simply copy the struct to and from that register location; there is no need to map anything.

Since bitfields are poorly specified by the C standard, and therefore most likely non-portable (especially not between big- and little endian cpus), the best thing is to get rid of them entirely and use the bitwise operators and bit masks instead. The resulting machine code will be identical, but the C code will be portable.

Also out of curiousity, which HCS12 derivate is that? I don't know of one that has an AD on address 270h. They usually don't support I/O from the A/D port either, just inputs.
0 Kudos
Reply

887 Views
Seegoon
Contributor I
hi there.
Thanks for the tips. I think I'll take your advice and change the way
these drivers work to make them more portable.
I'm using the mc9s12gc64. Here is a copy of the IO_Map.h (generated by processor expert)
 
I have managed to get it working by commenting out the definition of __PTAD , otherwise I get conflicts.
The address very well may not be at 0x270 , depends on what REG_BASE is.
As I said , I got it working , but its not elegant :0(
 
 
Code:
/*** PTAD - Port AD I/O Register; 0x00000270 ***/typedef union {  byte Byte;  struct {    byte PTAD0       :1;                                       /* Port AD Bit 0 */    byte PTAD1       :1;                                       /* Port AD Bit 1 */    byte PTAD2       :1;                                       /* Port AD Bit 2 */    byte PTAD3       :1;                                       /* Port AD Bit 3 */    byte PTAD4       :1;                                       /* Port AD Bit 4 */    byte PTAD5       :1;                                       /* Port AD Bit 5 */    byte PTAD6       :1;                                       /* Port AD Bit 6 */    byte PTAD7       :1;                                       /* Port AD Bit 7 */  } Bits;} PTADSTR;extern volatile PTADSTR _PTAD @(REG_BASE + 0x00000270);

 
0 Kudos
Reply

887 Views
bigmac
Specialist III
Hello Rob,
 
Assuming you are using Code Warrior, most of the work of defining individual bits within each register has already been done, within the header file for the device you are using.  You could create a similar bit field method for a custom declaration, using the header file as a model.  But it is probably simpler to just add a few custom macros to re-define the pin names, certainly for the individual pins used for LCD control.  For example -
 
#define ENABLE  PT1AD0_PT1AD01
#define RS      PT1AD0_PT1AD02
#define RW      PT1AD0_PT1AD03
 
DDR1AD0 = 0xFF;  /* Set port bits for output */
RW = 0;
RS = 0;
ENABLE = 1;
 
For handling the data nybble, an alternative might possibly be a more complex macro -
 
#define DATA_MASK 0xF0  /* Upper nybble */
#define LCD_DATA(data) PT1AD0 &= ~DATA_MASK; PT1AD0 |= ((data)<<4)
 
LCD_DATA('A'/16);  /* High nybble */
LCD_DATA('A'%16);  /* Low nybble */
 
You do not mention which HCS12 device you are using.  Perhaps you should check the address of the port register you are using.  Some devices seem to use an address of 0x0271, rather than 0x0270.  Of course, this is not an issue if you make use of the CW header.  Additionally, did you set the port bits for output?  The DDR setting may be opposite to what the PIC uses.
 
Regards,
Mac
 


Message Edited by bigmac on 2008-04-25 11:55 PM
0 Kudos
Reply