Setting Individual bits - HiTec

Thread Starter

ATM

Joined Oct 8, 2009
31
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;

#include <htc.h>
#include <pic.h>


void main()
{
TRISA1=1; //Set RA1 as input
TRISA4=0; //Set RA4 as output
However I have my doubts about the above and feel I am missing something fundamental.

Any help is appreciated, thanks.
 

mik3

Joined Feb 4, 2008
4,843
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?
 

AlexR

Joined Jan 16, 2008
732
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.
Rich (BB code):
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define flip_bit(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#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.
 

AlexR

Joined Jan 16, 2008
732
What does % stands for in HiTech?
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.
 

BMorse

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

Your code:
Rich (BB code):
TRISA1=1;            //Set RA1 as input
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 :

Rich (BB code):
/* Definitions for TRISA register */
               bit    TRISA0        @ ((unsigned)&TRISA*8)+0;
               bit    TRISA1        @ ((unsigned)&TRISA*8)+1;
               bit    TRISA2        @ ((unsigned)&TRISA*8)+2;
               bit    TRISA3        @ ((unsigned)&TRISA*8)+3;
               bit    TRISA4        @ ((unsigned)&TRISA*8)+4;
               bit    TRISA5        @ ((unsigned)&TRISA*8)+5;
               bit    TRISA6        @ ((unsigned)&TRISA*8)+6;
               bit    TRISA7        @ ((unsigned)&TRISA*8)+7;
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:
Rich (BB code):
PORTA = 0       ;//Always clear ports since they always default in random states 
TRISA = 0x02    ;//set RA1 as input and all the rest on PORTA as outputs
My .02
 
Last edited:

THE_RB

Joined Feb 11, 2008
5,438
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.
 

BMorse

Joined Sep 26, 2009
2,675
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.
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:

AlexR

Joined Jan 16, 2008
732
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
Rich (BB code):
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)
the source code
Rich (BB code):
#include <system.h>

#pragma DATA _CONFIG, _PWRTE_OFF & _WDT_OFF & _HS_OSC & _CP_OFF
#pragma CLOCK_FREQ    20000000    //Set clock frequency


void mydelay(int us)
{
    int s;
    for(s=0; s<us; s++);
}

void main( void )
{
    trisb = 0x00;                //Configure port b
    portb = 0xff;                //Initialize port b
    portb = 0x00;

    while(1)                    //Endless loop
    {
        delay_ms(250);
        set_bit(portb,1);        //setbit
        delay_ms(250);
        clear_bit(portb, 1);     //clearbit
    }

}
produces this assembler code
Rich (BB code):
;/////////////////////////////////////////////////////////////////////////////////
;// Code Generator: BoostC Compiler - http://www.sourceboost.com
;// Version       : 6.97
;// License Type  : Full License
;// Limitations   : PIC12,PIC16 max code size:Unlimited, max RAM banks:Unlimited, Non commercial use only
;/////////////////////////////////////////////////////////////////////////////////

    ORG 0x00000000
0000  2840      GOTO    _startup
    ORG 0x00000004
0004        delay_ms_00000
0004        ; { delay_ms ; function begin
0004  08A0      MOVF delay_ms_00000_arg_del, F
0005  1D03      BTFSS STATUS,Z
0006  2808      GOTO    label1
0007  0008      RETURN
0008        label1
0008  30F9      MOVLW 0xF9
0009        label2
0009  0000      NOP
000A  0000      NOP
000B  0000      NOP
000C  0000      NOP
000D  0000      NOP
000E  0000      NOP
000F  0000      NOP
0010  0000      NOP
0011  0000      NOP
0012  0000      NOP
0013  0000      NOP
0014  0000      NOP
0015  0000      NOP
0016  0000      NOP
0017  0000      NOP
0018  0000      NOP
0019  3EFF      ADDLW 0xFF
001A  1D03      BTFSS STATUS,Z
001B  2809      GOTO    label2
001C  0000      NOP
001D  0000      NOP
001E  0000      NOP
001F  0000      NOP
0020  0000      NOP
0021  0000      NOP
0022  0000      NOP
0023  0000      NOP
0024  0000      NOP
0025  0000      NOP
0026  0000      NOP
0027  0000      NOP
0028  0000      NOP
0029  0000      NOP
002A  0000      NOP
002B  0000      NOP
002C  0000      NOP
002D  0BA0      DECFSZ delay_ms_00000_arg_del, F
002E  2808      GOTO    label1
002F  0008      RETURN
0030        ; } delay_ms function end

    ORG 0x00000030
0030        main
0030        ; { main ; function begin
0030  1683      BSF STATUS, RP0
0031  1303      BCF STATUS, RP1
0032  0186      CLRF gbl_trisb
0033  30FF      MOVLW 0xFF
0034  1283      BCF STATUS, RP0
0035  0086      MOVWF gbl_portb
0036  0186      CLRF gbl_portb
0037        label3
0037  30FA      MOVLW 0xFA
0038  00A0      MOVWF delay_ms_00000_arg_del
0039  2004      CALL delay_ms_00000
003A  1486      BSF gbl_portb,1
003B  30FA      MOVLW 0xFA
003C  00A0      MOVWF delay_ms_00000_arg_del
003D  2004      CALL delay_ms_00000
003E  1086      BCF gbl_portb,1
003F  2837      GOTO    label3
0040        ; } main function end

    ORG 0x00000040
0040        _startup
0040  118A      BCF PCLATH,3
0041  120A      BCF PCLATH,4
0042  2830      GOTO    main
    ORG 0x00002007
2007  3FEA      DW 0x3FEA
The set_bit/clear_bit part of the code is in the label3 loop near the end of the file.
 

BMorse

Joined Sep 26, 2009
2,675
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.
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...
 

Thread Starter

ATM

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

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

#include <htc.h>
#include <pic.h>


void main()
{
TRISA1=1; //Set RA1 as input
TRISB4=0; //Set RB4 as output
CMCON = 0b00000010; //Configure the comparator register as 00000010
CVRCON = 0b11000100; //Configure the voltage comparator as 11000100
while(1)
{
RB4=CMCON,7;
}

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

THE_RB

Joined Feb 11, 2008
5,438
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. :)
 
Top