📄 lib_i2c.c
字号:
//*-----------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*-----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*-----------------------------------------------------------------------------
//* File Name : lib_i2c.c
//* Object : I2C driver functions
//*
//* 1.0 29/05/00 EL : Creation
//* 2.0 06/09/00 EL : Clean up
//* 2.1 21/11/00 JPP : Change Timer interrupt in LEVEL
//* 2.2 14/01/02 JPP : Send NACK at for read, and add wait function
//*-----------------------------------------------------------------------------
//* --------------------------- include file ----------------------------------
#include "lib_i2c.h"
#include "periph/power_saving/lib_power_save.h"
#include "periph/timer_counter/lib_tc.h"
//*-----------------------------------------------------------------------------
//* Internal function prototype
//*-----------------------------------------------------------------------------
void at91_I2CError(I2Cdesc *I2C_pt);
void at91_I2CSendStartSDA (I2Cdesc *I2C_pt);
void at91_I2CTxSendByte (I2Cdesc *I2C_pt);
void at91_I2CTxSendDeviceAddress (I2Cdesc *I2C_pt);
void at91_I2CTxSendBit (I2Cdesc *I2C_pt);
void at91_I2CRxReceiveByte (I2Cdesc *I2C_pt);
void at91_I2CRxReceiveBit (I2Cdesc *I2C_pt);
void at91_I2CSendStartSDA (I2Cdesc *I2C_pt);
void at91_I2CSendStartSCL (I2Cdesc *I2C_pt);
void at91_I2CPrepareSTOP (I2Cdesc *I2C_pt);
void at91_I2CPrepareACK (I2Cdesc *I2C_pt);
void at91_I2CTxWaitACK (I2Cdesc *I2C_pt);
void at91_I2CRxDoACK (I2Cdesc *I2C_pt);
void at91_I2CTxSetSCL (I2Cdesc *I2C_pt);
void at91_I2CTxClearSCL (I2Cdesc *I2C_pt);
void at91_I2CRxSetSCL (I2Cdesc *I2C_pt);
void at91_I2CRxClearSCL (I2Cdesc *I2C_pt);
//*-----------------------------------------------------------------------------
//* Internal function definition
//*-----------------------------------------------------------------------------
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2C (I2Cdesc *I2C_pt, u_short loadAddress, u_char nbByte)
//* Object : I2C
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* : loadAddress
//* : nbByte
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CDeviceRead (I2Cdesc *I2C_pt)
{ //* Begin
I2C_pt->pioa_base->PIO_OER = I2C_pt->SDA_line; //* set SDA line as an output
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SDA_line; //* set SDA line
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line; //* set SCL line
//* get byte to transmit
I2C_pt->I2CByte = I2C_pt->deviceAddress | READ_BIT ;
I2C_pt->mode = DATA_READ; //* next mode
I2C_pt->countBit = 8; //* initialize countBit
//* initialize nb_ACK
I2C_pt->nb_ACK = 10;
//* change interrupt handler to at91_I2CSendStartSDA
I2C_pt->I2CTCHandler = at91_I2CSendStartSDA;
} //* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CTxSendByte (I2Cdesc *I2C_pt)
//* Object : I2C
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CTxSendByte (I2Cdesc *I2C_pt)
{ //* Begin
I2C_pt->pioa_base->PIO_OER = I2C_pt->SDA_line; //* set SDA line as an output
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SDA_line; //* set SDA line
//* get byte to transmit
switch(I2C_pt->mode)
{
case DATA :
I2C_pt->I2CByte = *(I2C_pt->TxEnd++);
I2C_pt->nbI2CByte--;
if(I2C_pt->nbI2CByte == 0)
//* next mode
I2C_pt->mode = STOP;
break;
case HIGH_ADDRESS_WRITE :
I2C_pt->I2CByte = (u_char) (I2C_pt->loadAddress >> 8);
//* next mode
I2C_pt->mode = LOW_ADDRESS_WRITE;
break;
case LOW_ADDRESS_WRITE :
I2C_pt->I2CByte = (u_char) I2C_pt->loadAddress;
//* next mode
I2C_pt->mode = DATA;
break;
case HIGH_ADDRESS_READ :
I2C_pt->I2CByte = (u_char) (I2C_pt->loadAddress >> 8);
//* next mode
I2C_pt->mode = LOW_ADDRESS_READ;
break;
case LOW_ADDRESS_READ :
I2C_pt->I2CByte = (u_char) I2C_pt->loadAddress;
//* next mode
I2C_pt->mode = DEVICE_READ;
break;
}
I2C_pt->countBit = 8; //* initialize countBit
I2C_pt->nb_ACK = 10; //* initialize nb_ACK
//* change interrupt handler to at91_I2CTxSendBit
I2C_pt->I2CTCHandler = at91_I2CTxSendBit;
} //* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CTxSendBit (I2Cdesc *I2C_pt)
//* Object :
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CTxSendBit (I2Cdesc *I2C_pt)
{//* Begin
u_char bit_val;
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line; //* Clear SCL line
//* decrement countBit
I2C_pt->countBit--;
//* if bit counter = 0
if(I2C_pt->countBit >= 0)
{
//* get bit to transfert
bit_val = (I2C_pt->I2CByte >> I2C_pt->countBit) & 1;
//* Send 0 or 1
if (bit_val)
//* Set SDA line
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SDA_line;
else
//* Clear SDA line
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SDA_line;
//* change interrupt handler to at91_I2CTxSetSCL
I2C_pt->I2CTCHandler = at91_I2CTxSetSCL;
}
else
{
//* set SDA line as an input
I2C_pt->pioa_base->PIO_ODR = I2C_pt->SDA_line;
//* change interrupt handler to at91_I2CPrepareACK
I2C_pt->I2CTCHandler = at91_I2CPrepareACK;
}
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CSendStartSDA (I2Cdesc *I2C_pt)
//* Object : clear SDA line
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CSendStartSDA (I2Cdesc *I2C_pt)
{//* Begin
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SDA_line; //* clear SDA line
//* change interrupt handler to at91_I2CSendStartSCL
I2C_pt->I2CTCHandler = at91_I2CSendStartSCL;
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CTxSendStart (I2Cdesc *I2C_pt)
//* Object : clear SCL line
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CSendStartSCL (I2Cdesc *I2C_pt)
{//* Begin
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line; //* clear SCL line
//* change interrupt handler to at91_I2CTxSendBit
I2C_pt->I2CTCHandler = at91_I2CTxSendBit;
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CPrepareSTOP (I2Cdesc *I2C_pt)
//* Object :
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CPrepareSTOP (I2Cdesc *I2C_pt)
{//* Begin
I2C_pt->pioa_base->PIO_OER = I2C_pt->SDA_line; //* set SDA line as an output
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SDA_line; //* clear SDA line
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line; //* set SCL line
//* change interrupt handler to at91_I2CSendStopSDA
I2C_pt->I2CTCHandler = at91_I2CSendStopSDA;
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CSendStopEND (I2Cdesc *I2C_pt)
//* Object : end of transmistion
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CSendStopEND (I2Cdesc *I2C_pt)
{//* Begin
//* Disable RC compare interrupt
I2C_pt->timerBase->TC_IDR = TC_CPCS;
//* change interrupt handler to
I2C_pt->I2CTCHandler = no_handler_tc;
//* set the End state
I2C_pt->state = OK;
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CSendStopSDA (I2Cdesc *I2C_pt)
//* Object : set SDA and ans load end for stop
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CSendStopSDA (I2Cdesc *I2C_pt)
{//* Begin
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SDA_line; //* set SDA line
//* change interrupt handler to
I2C_pt->I2CTCHandler = at91_I2CSendStopEND;
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CPrepareACK (I2Cdesc *I2C_pt)
//* Object : set SCL line and load at91_I2CTxWaitACK
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CPrepareACK (I2Cdesc *I2C_pt)
{//* Begin
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line; //* set SCL line
//* change interrupt handler to at91_I2CTxWaitACK
I2C_pt->I2CTCHandler = at91_I2CTxWaitACK;
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CRxPrepareACK (I2Cdesc *I2C_pt)
//* Object :
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CRxPrepareACK (I2Cdesc *I2C_pt)
{//* Begin
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line; //* set SCL line
if(I2C_pt->mode == STOP)
//* change interrupt handler to
I2C_pt->I2CTCHandler = at91_I2CPrepareSTOP;
else
//* change interrupt handler to at91_I2CRxDoACK
I2C_pt->I2CTCHandler = at91_I2CRxDoACK;
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CTxWaitACK (I2Cdesc *I2C_pt)
//* Object :
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CTxWaitACK (I2Cdesc *I2C_pt)
//* Begin
{
//* if ACK (SDA = 0)
if((I2C_pt->pioa_base->PIO_PDSR & I2C_pt->SDA_line) == 0)
{
switch(I2C_pt->mode)
{
case STOP :
//* clear SCL line
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;
//* change interrupt handler to
I2C_pt->I2CTCHandler = at91_I2CPrepareSTOP;
break;
case DEVICE_READ :
//* clear SCL line
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;
//* change interrupt handler to
I2C_pt->I2CTCHandler = at91_I2CDeviceRead;
break;
case DATA_READ :
//* change interrupt handler to
I2C_pt->I2CTCHandler = at91_I2CRxReceiveByte;
break;
default :
//* clear SCL line
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line;
//* change interrupt handler to
I2C_pt->I2CTCHandler = at91_I2CTxSendByte;
break;
} //* End switch
}
else
{
I2C_pt->nb_ACK--;
if(I2C_pt->nb_ACK == 0)
//* change interrupt handler to at91_I2C
I2C_pt->I2CTCHandler = at91_I2CError;
}
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CRxDoACK (I2Cdesc *I2C_pt)
//* Object : clear SCL line and load RxReceiveByte
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CRxDoACK (I2Cdesc *I2C_pt)
{//* Begin
I2C_pt->pioa_base->PIO_CODR = I2C_pt->SCL_line; //* clear SCL line
//* change interrupt handler to
I2C_pt->I2CTCHandler = at91_I2CRxReceiveByte;
}//* End
//*-----------------------------------------------------------------------------
//* Function Name : at91_I2CTxSetSCL (I2Cdesc *I2C_pt)
//* Object : set SCL line
//* Input Parameters : <I2C_pt> = I2C Peripheral Descriptor pointer
//* Output Parameters : none
//*-----------------------------------------------------------------------------
void at91_I2CTxSetSCL (I2Cdesc *I2C_pt)
{//* Begin
I2C_pt->pioa_base->PIO_SODR = I2C_pt->SCL_line; //* set SCL line
//* change interrupt handler to at91_I2CTxSendBit
I2C_pt->I2CTCHandler = at91_I2CTxSendBit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -