Setting Individual bits - HiTec

Discussion in 'Embedded Systems and Microcontrollers' started by ATM, Nov 29, 2009.

  1. ATM

    Thread Starter Member

    Oct 8, 2009
    31
    0
    Hey, fairly new to pic programming. I'm using a Pic16f88, MPLAB and the Hi-Tech C compiler. I need to set pins RA1 as input and RA4 as output.

    I've tried a few different syntax;

    TRISAbits.TRISA1=1;
    TRISAbits.TRISA4=0;

    TRISA=%00000010;
    TRISA=%00000000;

    Neither of these two compile correctly. The only way I can get the program to compile is by stating;

    However I have my doubts about the above and feel I am missing something fundamental.

    Any help is appreciated, thanks.
     
  2. mik3

    Senior Member

    Feb 4, 2008
    4,846
    63
    I am not using HiTech but with other compilers to set the I/O pins you can use for example:

    TRISA=0b0000001;

    where 0b stands for binary number.

    It can be written in decimal as:

    TRISA=1;

    or HEX

    TRISA=0x1;

    What does % stands for in HiTech?
     
  3. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    Place the following lines near the start of your source code or better still make a header file with the code below and include it in your source.
    Code ( (Unknown Language)):
    1. #define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
    2. #define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
    3. #define flip_bit(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
    4. #define test_bit(ADDRESS,BIT) (ADDRESS & (1<<BIT))
    Then to set bit one of TRISA your command would be
    set_bit(TRISA, 1);
    To clear a bit it woulld be clear_bit(TRISA, 3); and so on.
     
  4. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    Modulus, the same as in all other C compilers!

    But what mik3 says is right. If you are setting up ports and port direction registers you are better off writing the whole configuration word in binary or hex rather than setting one bit at a time.
    There are however occasions when you do need to manipulate bits and the macros above make it easy and the code understandable.
     
  5. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234
    Ok looking at the way Hi-Tech declares stuff in their include files ... (It is amazing what you learn when reading documentation ;)!)

    Your code:
    Code ( (Unknown Language)):
    1.  
    2. TRISA1=1;            //Set RA1 as input
    3. TRISA4=0;            //Set RA4 as output                      
    is the correct way to set an individual bit in Hi-Tech C....

    according to the include file for these devices :

    Code ( (Unknown Language)):
    1. /* Definitions for TRISA register */
    2.                bit    TRISA0        @ ((unsigned)&TRISA*8)+0;
    3.                bit    TRISA1        @ ((unsigned)&TRISA*8)+1;
    4.                bit    TRISA2        @ ((unsigned)&TRISA*8)+2;
    5.                bit    TRISA3        @ ((unsigned)&TRISA*8)+3;
    6.                bit    TRISA4        @ ((unsigned)&TRISA*8)+4;
    7.                bit    TRISA5        @ ((unsigned)&TRISA*8)+5;
    8.                bit    TRISA6        @ ((unsigned)&TRISA*8)+6;
    9.                bit    TRISA7        @ ((unsigned)&TRISA*8)+7;
    10.  
    TRISA1 and TRISA4 is the correct syntax for doing what you want....


    or you could do it this way as others are suggesting in setting the whole port at once:
    Code ( (Unknown Language)):
    1.  
    2. PORTA = 0       ;//Always clear ports since they always default in random states
    3. TRISA = 0x02    ;//set RA1 as input and all the rest on PORTA as outputs
    My .02
     
    Last edited: Nov 29, 2009
  6. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    That looks barbaric! :eek:

    Assuming PIC 16F or 18F series, what output does the compiler generate for;
    PORTA3 = 1;

    That should compile down to;
    BSF PORTA,3

    I'm amazed that soneone would make a C compiler for PICs that doesn't work properly with bits. That's one of the reasons I like MikroC, it works on a compiler level with bits;
    PORTA.F3 = 1; compiles to; BSF PORTA,3 (as it should) and you can use binary data type; PORTA = 0b00001000 which is a necessity I think.
     
  7. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234
    yes, PORTA = 3; will compile down to equal bsf PORTA,3

    and you could do both in the Hi-Tech C also with the ports:

    TRISA=b'00001000' ; is the same as :
    movlw b'00001000' ;
    movwf TRISA ;

    This seems to be confusing others also when trying to assign data to individual bits in Hi-Tech C, (This is my first using this compiler) but from what I have read and tried already, I think their approach is a little more staright forward when setting individual bits, don't have to memorize long syntax :

    (Hi-tech C) PORTA3 = 1;

    (MicroC) PORTA.F3 = 1;

    for beginners, I believe the Hi-Tech C syntax would be easier to remember.... Like I said I just started to get into the workings of this Hi-Tech C compiler, and I am still learning the differences in syntax from one C compiler to another.
     
    Last edited: Nov 30, 2009
  8. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    The problem with both the Hi-Tech C notation and the MicroC notation for bit manipulation is that nether conform to the ANSI C standard, what's more each adopt there own specific syntax. This makes porting code between compilers a real PITA.
    Using the macro approach produces code that will compile on any version of C compiler and will optimise down to single BSF/BCF assembler statements.

    Using the macros
    Code ( (Unknown Language)):
    1. #define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
    2. #define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)
    the source code
    Code ( (Unknown Language)):
    1. #include <system.h>
    2.  
    3. #pragma DATA _CONFIG, _PWRTE_OFF & _WDT_OFF & _HS_OSC & _CP_OFF
    4. #pragma CLOCK_FREQ    20000000    //Set clock frequency
    5.  
    6.  
    7. void mydelay(int us)
    8. {
    9.     int s;
    10.     for(s=0; s<us; s++);
    11. }
    12.  
    13. void main( void )
    14. {
    15.     trisb = 0x00;                //Configure port b
    16.     portb = 0xff;                //Initialize port b
    17.     portb = 0x00;
    18.  
    19.     while(1)                    //Endless loop
    20.     {
    21.         delay_ms(250);
    22.         set_bit(portb,1);        //setbit
    23.         delay_ms(250);
    24.         clear_bit(portb, 1);     //clearbit
    25.     }
    26.  
    27. }
    28.  
    29.  
    produces this assembler code
    Code ( (Unknown Language)):
    1. ;/////////////////////////////////////////////////////////////////////////////////
    2. ;// Code Generator: BoostC Compiler - [URL]http://www.sourceboost.com[/URL]
    3. ;// Version       : 6.97
    4. ;// License Type  : Full License
    5. ;// Limitations   : PIC12,PIC16 max code size:Unlimited, max RAM banks:Unlimited, Non commercial use only
    6. ;/////////////////////////////////////////////////////////////////////////////////
    7.  
    8.     ORG 0x00000000
    9. 0000  2840      GOTO    _startup
    10.     ORG 0x00000004
    11. 0004        delay_ms_00000
    12. 0004        ; { delay_ms ; function begin
    13. 0004  08A0      MOVF delay_ms_00000_arg_del, F
    14. 0005  1D03      BTFSS STATUS,Z
    15. 0006  2808      GOTO    label1
    16. 0007  0008      RETURN
    17. 0008        label1
    18. 0008  30F9      MOVLW 0xF9
    19. 0009        label2
    20. 0009  0000      NOP
    21. 000A  0000      NOP
    22. 000B  0000      NOP
    23. 000C  0000      NOP
    24. 000D  0000      NOP
    25. 000E  0000      NOP
    26. 000F  0000      NOP
    27. 0010  0000      NOP
    28. 0011  0000      NOP
    29. 0012  0000      NOP
    30. 0013  0000      NOP
    31. 0014  0000      NOP
    32. 0015  0000      NOP
    33. 0016  0000      NOP
    34. 0017  0000      NOP
    35. 0018  0000      NOP
    36. 0019  3EFF      ADDLW 0xFF
    37. 001A  1D03      BTFSS STATUS,Z
    38. 001B  2809      GOTO    label2
    39. 001C  0000      NOP
    40. 001D  0000      NOP
    41. 001E  0000      NOP
    42. 001F  0000      NOP
    43. 0020  0000      NOP
    44. 0021  0000      NOP
    45. 0022  0000      NOP
    46. 0023  0000      NOP
    47. 0024  0000      NOP
    48. 0025  0000      NOP
    49. 0026  0000      NOP
    50. 0027  0000      NOP
    51. 0028  0000      NOP
    52. 0029  0000      NOP
    53. 002A  0000      NOP
    54. 002B  0000      NOP
    55. 002C  0000      NOP
    56. 002D  0BA0      DECFSZ delay_ms_00000_arg_del, F
    57. 002E  2808      GOTO    label1
    58. 002F  0008      RETURN
    59. 0030        ; } delay_ms function end
    60.  
    61.     ORG 0x00000030
    62. 0030        main
    63. 0030        ; { main ; function begin
    64. 0030  1683      BSF STATUS, RP0
    65. 0031  1303      BCF STATUS, RP1
    66. 0032  0186      CLRF gbl_trisb
    67. 0033  30FF      MOVLW 0xFF
    68. 0034  1283      BCF STATUS, RP0
    69. 0035  0086      MOVWF gbl_portb
    70. 0036  0186      CLRF gbl_portb
    71. 0037        label3
    72. 0037  30FA      MOVLW 0xFA
    73. 0038  00A0      MOVWF delay_ms_00000_arg_del
    74. 0039  2004      CALL delay_ms_00000
    75. 003A  1486      BSF gbl_portb,1
    76. 003B  30FA      MOVLW 0xFA
    77. 003C  00A0      MOVWF delay_ms_00000_arg_del
    78. 003D  2004      CALL delay_ms_00000
    79. 003E  1086      BCF gbl_portb,1
    80. 003F  2837      GOTO    label3
    81. 0040        ; } main function end
    82.  
    83.     ORG 0x00000040
    84. 0040        _startup
    85. 0040  118A      BCF PCLATH,3
    86. 0041  120A      BCF PCLATH,4
    87. 0042  2830      GOTO    main
    88.     ORG 0x00002007
    89. 2007  3FEA      DW 0x3FEA
    90.  
    91.  
    The set_bit/clear_bit part of the code is in the label3 loop near the end of the file.
     
  9. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234
    That is one thing I do not like about these compilers is their syntax.... why can't they just stick to a standard instead of trying to start their own?

    I see what you mean if you do try to port it over you would have to change quite a bit of code, your way seems easier to port...
     
  10. ATM

    Thread Starter Member

    Oct 8, 2009
    31
    0
    Thanks for the input guys, appreciated.

    I have another question that is also related to my first, I have the code:

    If I wanted to output the value of CMCON bit 7 onto pin RB4, is the above syntax correct?
     
  11. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    Thanks for the information. I didn't know the macro would compile down to a single BSF or BCF instruction. I just tested your 2 macros on MikroC and it weems to work fine. :)
     
Loading...