CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

How to set TRIS for single pin without affect port state

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

How to set TRIS for single pin without affect port state
PostPosted: Wed Sep 09, 2015 1:54 pm     Reply with quote

I need to buid a driver for a device with I2C protocol , but without use CCS built in I2C function , that because i want to be available for devices without I2C and for diferent clock speed. I want to set TRIS in time of executing program without change the stats of others pins of port .


Code:
//  I2C level
typedef enum{
  LOW                      = 0,
  HIGH                     = 1,
}etI2cLevel;


Code:

#define SDA_STATE  ??????(i want to set tris in or out)
#define SDA_CONF   output_bit(xxx_pin, 1)
#define SCK_STATE  ??????(i want to set tris in or out)
#define SCK_CONF   output_bit(yyy_pin, 1)

I want the LOW and HIGH def to configure the pin defined , on SCK_CONF and SDA_CONF is simple with output_bit function, but for SDA_STATE & SCK_STATE i want to be configure during the program , with same argument 0,1 . I think i need to made a function that acces and set the registry , right? I know i can set as input with output_float() function and the compiler choose the best option for TRIS on each pin , but now i need to do it manualy . Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Wed Sep 09, 2015 2:09 pm     Reply with quote

Output_float, does not "choose the best option for TRIS on each pin ". It changes only the pin you tell it.

output_float(PIN_A1); sets the TRIS bit on pin A1, to '1'.
output_drive(PIN_A1); sets the TRIS bit on pin A1 to '0'.

Exactly what you want.

If you want ot take complete control of the TRIS for the port (turn off the automatic control), then just use #use fast_io(A) (or B, C etc..
Once this is used, the compiler will completely stop controlling the TRIS on port A (or B, C etc.). It then becomes up to _you_ to set it, clear it, etc..
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Wed Sep 09, 2015 2:16 pm     Reply with quote

Ttelmah wrote:

If you want ot take complete control of the TRIS for the port (turn off the automatic control), then just use #use fast_io(A) (or B, C etc..
Once this is used, the compiler will completely stop controlling the TRIS on port A (or B, C etc.). It then becomes up to _you_ to set it, clear it, etc..


Curiosity:

How does fast_io work with I2C given that you have to both control the lines and release them to the slave? If you enable fast_io, do you have to gen your own I2C functions or do they still force input/output for release/control portions of the protocol?
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Sep 09, 2015 3:08 pm     Reply with quote

I think now will work like that

Code:

#define SDA_STATE  ctrl_DAT(x)
#define SDA_CONF   output_bit(xxx_pin, 1)
#define SCK_STATE  ctrl_CLK(y)
#define SCK_CONF   output_bit(yyy_pin, 1)


Code:
void ctrl_DAT(int8 state)
{
   switch(state)
   {
      case 0:
         output_drive(PIN_Bx);
         break;
      case 1:
         output_float(PIN_Bx);
         break;
      default:
         break;
   }
}

void ctrl_CLK(int8 state)
{
   switch(state)
   {
      case 0:
         output_drive(PIN_By);
         break;
      case 1:
         output_float(PIN_By);
         break;
      default:
         break;
   }
}

Thanks , i didn't know output_drive() function exist in CCS because i never use TRIS in CCS, is so simply now.
Exist other better option to do that ?
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Thu Sep 10, 2015 12:49 pm     Reply with quote

I want to notice, if i use output_drive() function, the compiler stuck in last state of port. Dont matter if other function set the pin as input, compiler keep that as output low or high, how has last intruction. I try fixed IO, fast IO, but same result. I close to do manually all function i need for init/start/stop/read/write and acknowledge bit on I2C.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 10, 2015 7:36 pm     Reply with quote

What is this ?
Code:
PIN_Bx

Is it a constant like PIN_B4, or is it a variable ?

You're doing these posts where you give partial information, and there
is no easy way for us to understand your exact problem.
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Fri Sep 11, 2015 7:21 am     Reply with quote

PCM programmer wrote:
What is this ?
Code:
PIN_Bx

Is it a constant like PIN_B4, or is it a variable ?

You're doing these posts where you give partial information, and there
is no easy way for us to understand your exact problem.


I apologize , to be more clear , i try to made a driver for SHT2x series ,without use default I2C port of PIC , that will be portable for any PIC family . Exist already some samples code on sensirion website , but need to be ported on PIC-C .
Code:
//~~~~~~ declarations ~~~~~~~~~~~~~~
#define sda_pin PIN_B0
#define scl_pin PIN_B1

#define SDA   ctrl_DAT(0)             //SDA on I/O  defines direction (input=1/output=0)
#define SDA_CONF   output_bit(sda_pin, 1)    //SCL level on output direction
#define SDA_READ  input_state(sda_pin)      // read status of input pin
#define SCL    ctrl_CLK(0)             //SCL on I/O  defines direction (input=1/output=0)
#define SCL_CONF   output_bit(scl_pin, 1)   //SCL level on output direction
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  I2C level
typedef enum{
  LOW                      = 0,
  HIGH                     = 1,
}etI2cLevel;

// I2C acknowledge
typedef enum{
  ACK                      = 0,
  NO_ACK                   = 1,
}etI2cAck;
// Error codes
typedef enum{
  ACK_ERROR                = 0x01,
  TIME_OUT_ERROR           = 0x02,
  CHECKSUM_ERROR           = 0x04,
  UNIT_ERROR               = 0x08
}etError;

Function that control SDA SCL pins status .
Code:
//~~~~~~~~~~~~~~~~~~change sda scl status ~~~~~~~~~~~~~~~~~~~~~
void ctrl_DAT(int1 state)
{
   switch(state)
   {
      case 0:
         output_drive(sda_pin);
         break;
      case 1:
         output_float(sda_pin);
         break;
      default:
         break;
   }
}

void ctrl_CLK(int1 state)
{
   switch(state)
   {
      case 0:
         output_drive(scl_pin);
         break;
      case 1:
         output_float(scl_pin);
         break;
      default:
         break;
   }
}

Delay function permit to adjust SCL/SDA timing on various osc

Code:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void DelayMicroSeconds (int32 nbrOfUs)
{
//   int32 i  = 0;
  for(int32 i=0; i<nbrOfUs; i++)
  { 
//   delay_cycles(3);   //8M osc
   delay_us(1);
  }
}

And I2C functions
Code:
//==============================================================================
void I2c_Initialize ()
//==============================================================================
{
  SDA=LOW;                // Set port as output for configuration
  SCL=LOW;                // Set port as output for configuration

  SDA_CONF=LOW;           // Set SDA level as low for output mode
  SCL_CONF=LOW;           // Set SCL level as low for output mode

  SDA=HIGH;               // I2C-bus idle mode SDA released (input)
  SCL=HIGH;               // I2C-bus idle mode SCL released (input)
}

//==============================================================================
void I2c_StartCondition ()
//==============================================================================
{
  SDA=HIGH;
  SCL=HIGH;
  SDA=LOW;
  DelayMicroSeconds(10);  // hold time start condition (t_HD;STA)
  SCL=LOW;
  DelayMicroSeconds(10);
}

//==============================================================================
void I2c_StopCondition ()
//==============================================================================
{
  SDA=LOW;
  SCL=LOW;
  SCL=HIGH;
  DelayMicroSeconds(10);  // set-up time stop condition (t_SU;STO)
  SDA=HIGH;
  DelayMicroSeconds(10);
}

//==============================================================================
int8 I2c_WriteByte (int8 txByte)
//==============================================================================
{
  int8 mask,error=0;
  for (mask=0x80; mask>0; mask>>=1)   //shift bit for masking (8 times)
  { if ((mask & txByte) == 0) SDA = LOW;//masking txByte, write bit to SDA-Line
    else SDA = HIGH;
    DelayMicroSeconds(1);             //data set-up time (t_SU;DAT)
    SCL=HIGH;                         //generate clock pulse on SCL
    DelayMicroSeconds(5);             //SCL high time (t_HIGH)
    SCL=LOW;
    DelayMicroSeconds(1);             //data hold time(t_HD;DAT)
  }
  SDA=HIGH;                           //release SDA-line
  SCL=HIGH;                           //clk #9 for ack
  DelayMicroSeconds(1);               //data set-up time (t_SU;DAT)
  if(SDA_READ==HIGH) error=ACK_ERROR; //check ack from i2c slave
  SCL=LOW;
  DelayMicroSeconds(20);              //wait time to see byte package on scope
  return error;                       //return error code
}

//==============================================================================
int8 I2c_ReadByte (etI2cAck ack)
//==============================================================================
{
  int8 mask,rxByte=0;
  SDA=HIGH;                           //release SDA-line
  for (mask=0x80; mask>0; mask>>=1)   //shift bit for masking (8 times)
  { SCL=HIGH;                         //start clock on SCL-line
    DelayMicroSeconds(1);             //data set-up time (t_SU;DAT)
    DelayMicroSeconds(3);             //SCL high time (t_HIGH)
    if (SDA_READ==1) rxByte=(rxByte | mask); //read bit
    SCL=LOW;
    DelayMicroSeconds(1);             //data hold time(t_HD;DAT)
  }
  SDA=ack;                            //send acknowledge if necessary
  DelayMicroSeconds(1);               //data set-up time (t_SU;DAT)
  SCL=HIGH;                           //clk #9 for ack
  DelayMicroSeconds(5);               //SCL high time (t_HIGH)
  SCL=LOW;
  SDA=HIGH;                           //release SDA-line
  DelayMicroSeconds(20);              //wait time to see byte package on scope
  return rxByte;                      //return error code
}

Like i say, if i use output_drive() function and i do some write address without ack, the controller made first pulse and after go in output_drive() function, the stat of pin as I/O will never change.


Last edited by wangine on Fri Sep 11, 2015 11:52 am; edited 1 time in total
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Fri Sep 11, 2015 8:55 am     Reply with quote

Code:

SDA=HIGH;                           //release SDA-line


I may be missing something, but your comment indicates you want to release the SDA line while your code "drives" the SDA line, not permitting the slave to ack or nack. You would need to float the line at this point so the slave can choose to drive it low if it wants to.

Similar issues in other spots.
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Fri Sep 11, 2015 11:59 am     Reply with quote

jeremiah wrote:
Code:

SDA=HIGH;                           //release SDA-line


I may be missing something, but your comment indicates you want to release the SDA line while your code "drives" the SDA line, not permitting the slave to ack or nack. You would need to float the line at this point so the slave can choose to drive it low if it wants to.

Similar issues in other spots.

Yes that will do ctrl_DAT(int1 state) function , if state is HIGH - 0 will release SDA line , is float in case 1 , state 0 is output_drive() , im so confused right now
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

PostPosted: Sun Sep 13, 2015 7:17 am     Reply with quote

It seems that much of the confusion expressed in this thread is over what specifically the various CCS library functions, like output_float(PIN_A1), actually do. I suggest that for simple functions like this, it is best to skip the CCS library altogether and use more primitive instructions. For example, if somewhere in your project's processor-specific includes you have:

Code:
struct {
   unsigned int RA0:1;
   unsigned int RA1:1;
   unsigned int RA2:1;
   unsigned int RA3:1;
   unsigned int RA4:1;
   unsigned int RA5:1;
   unsigned int RA6:1;
   unsigned int RA7:1;
} TRISA;
#byte TRISA = 0xF92


Then the TRISA register can be set all at once with the C instruction:

Code:
TRISA = 0b11111101;   //..(all inputs except for RA1)


This compiles to two machine instructions, and is as efficient as it can be. Also it is understandable. You just need to know your processor and its registers, which you really should know anyway, even when you are using the CCS library to insulate you from a first-level understanding of those registers.

Furthermore, you can declare application-specific names for the bits of PORTA and its TRIS register as in:

Code:
#define MotorStatusTrisBit   TRISA.RA1


So now you can write:

Code:
MotorStatusTrisBit = 1;   //..make RA1 go floating
MotorStatusTrisBit = 0;   //..drive RA1 as an output


Each of these statements compile to a single bit-setting or bit-clearing machine instruction and do just what output_float(PIN_A1) and output_drive(PIN_A1) would do (set or clear just one bit and leave the rest as they were) without the need to reference the CCS library.

In many cases the CCS library presents a simpler interface to complicated functions, but not in this case. In this case the CCS library presents an interface that is no simpler than the primitive register access itself, so why bother with the CCS library here?
_________________
Robert Scott
Real-Time Specialties
Embedded Systems Consulting
wangine



Joined: 07 Jul 2009
Posts: 98
Location: Curtea de Arges, Romania

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Sun Sep 13, 2015 6:00 pm     Reply with quote

Yes, a great answer. I don't know why i don't think of it by myself. Some years ago i has same problem with dsPIC33FJ128MC804 with FRC and PLL to bring up to 80Mhz, also with ADC function, was impossible to init with CCS function like I wish,
Code:

void initAdc1(void)
{

AD1CON1bits.FORM   = 0b00;   // Data Output Format: Signed Fraction (Q15 format)// facut unsigned fost 3 pt1023=0b00
AD1CON1bits.SSRC   = 2;   // Sample Clock Source: GP Timer starts conversion
AD1CON1bits.ASAM   = 1;   // ADC Sample Control: Sampling begins immediately after conversion
AD1CON1bits.AD12B  = 0;   // 10-bit ADC operation

// AD1CON2bits.CSCNA = 1;   // Scan Input Selections for CH0+ during Sample A bit
AD1CON2bits.CHPS  = 0;   // Converts CH0

AD1CON3bits.ADRC = 0;   //0   // ADC Clock is derived from Systems Clock
AD1CON3bits.ADCS = 1;   //63   // ADC Conversion Clock Tad=Tcy*(ADCS+1)= (1/40M)*64 = 1.6us (625Khz)
// ADC Conversion Time for 10-bit Tc=12*Tab = 19.2us
//   setup_adc( ADC_TAD_MUL_4);
setup_adc_ports( VSS_VDD);

AD1CON2bits.SMPI    = (NUM_CHS2SCAN-1);   // 4 ADC Channel is scanned

//AD1CSSH/AD1CSSL: A/D Input Scan Selection Register
///?   AD1CSSH = 0x0000;         
AD1CSSLbits.CSS0=1;   // Enable AN0 for channel scan

Just a piece of code, I was forced to modify originally dsPIC.h file with some structures that access each register, like you say, primitive functions but also very fast access. QEI module was same problem. Thanks alot, you opened my mind again.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group