?? i2c_master.c
字號:
/**************************************************************************************
In this case we use I2C1 as the I2C communication master->
By default, it operates in slave mode. The interface automatically switches from slave to
master, after it generates a START condition and from master to slave, if an arbitration loss
or a Stop generation occurs, allowing multimaster capability.
In Master mode, the I2C interface initiates a data transfer and generates the clock signal. A
serial data transfer always begins with a start condition and ends with a stop condition. Both
start and stop conditions are generated in master mode by software.
***************************************************************************************/
#include "I2C.h"
#include "stm32f10x_map.h"
#include "stm32f10x_rcc.h"
#define I2C1 ((I2C_TypeDef *) I2C1_BASE)
/************************************************************************************8
Function Name:I2C_MasterIni()
Function:To initiate the I2C controllor as an I2C master->
Parameter:I2C_TypeDef *I2C1:The target I2C controllor->
Return:none
Note:The following is the required sequence in master mode:
1.Program the peripheral input clock in I2C_CR2 Register in order to generate correct timings.
2.Configure the clock control registers.
3.Configure the rise time register.TRISE[5:0] must be configured only when the I2C is disabled (PE = 0).
4.Program the I2C_CR1 register to enable the peripheral.
5.Set the START bit in the I2C_CR1 register to generate a Start condition.
*************************************************************************************/
void I2C_MasterIni(void)
{
I2C1->CR2 =0x0104; //The peripheral`s input clock is 36 MHz
I2C1->CCR =0x821C; //cinfigure the clock control rigester as:Standard Mode,100KHz.Because the input clock is 36MHz,so to meet the 100KHZ bus clock demand ,TCK=1s/36MHZ,Tow=Thigh=5000ns,CCR[11:0]=Tow/TCK=180d=B4h
I2C1->TRISE =0x0022; //configure the rise time rigester as :The maximum rising time in standard mode is 1000 ns.So TRISE=(1000ns/(1s/36MHz))+1
I2C1->CR1 |=0x0401; //Set ACK (Acknowledge returned after a byte is received (matched address or data)).Set PE bit to enable this peripheral.
}
/*void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct)
{
u16 tmpreg = 0, freqrange = 0;
u16 result = 0x04;
u32 pclk1clock = 12000000;
RCC_ClocksTypeDef RCC_Clocks;
/* Check the parameters */
/* assert_param(IS_I2C_MODE(I2C_InitStruct->I2C_Mode));
assert_param(IS_I2C_DUTY_CYCLE(I2C_InitStruct->I2C_DutyCycle));
assert_param(IS_I2C_OWN_ADDRESS1(I2C_InitStruct->I2C_OwnAddress1));
assert_param(IS_I2C_ACK_STATE(I2C_InitStruct->I2C_Ack));
assert_param(IS_I2C_ACKNOWLEDGE_ADDRESS(I2C_InitStruct->I2C_AcknowledgedAddress));
assert_param(IS_I2C_CLOCK_SPEED(I2C_InitStruct->I2C_ClockSpeed));
/*---------------------------- I2Cx CR2 Configuration ------------------------*/
/* Get the I2Cx CR2 value */
/* tmpreg = I2Cx->CR2;
/* Clear frequency FREQ[5:0] bits */
/* tmpreg &= CR2_FREQ_Reset;
/* Get PCLK1Clock frequency value */
/* RCC_GetClocksFreq(&RCC_Clocks);
pclk1clock = RCC_Clocks.PCLK1_Frequency;
/* Set frequency bits depending on PCLK1Clock value */
/* freqrange = (u16)(pclk1clock / 1000000);
tmpreg |= freqrange;
/* Write to I2Cx CR2 */
// I2Cx->CR2 = tmpreg;
/*---------------------------- I2Cx CCR Configuration ------------------------*/
/* Disable I2Cx to configure TRISE */
// I2C_Cmd(I2Cx, DISABLE);
/* Reset tmpreg value */
/* Clear F/S, DUTY and CCR[11:0] bits */
// tmpreg = 0;
/* Configure speed in standard mode */
/* if (I2C_InitStruct->I2C_ClockSpeed <= 100000)
{
/* Standard mode speed calculate */
// result = (u16)(pclk1clock / (I2C_InitStruct->I2C_ClockSpeed << 1));
/* Test if CCR value is under 0x4*/
/* if (result < 0x04)
{
/* Set minimum allowed value */
/* result = 0x04;
}
/* Set speed value for standard mode */
// tmpreg |= result;
/* Set Maximum Rise Time: ((1000/(1000000000/pclk1clock))+1 */
/* I2Cx->TRISE = freqrange + 1;
}
/* Configure speed in fast mode */
// else /*(I2C_InitStruct->I2C_ClockSpeed <= 400000)*/
/* {
if (I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_2)
{
/* Fast mode speed calculate: Tlow/Thigh = 2 */
/* result = (u16)(pclk1clock / (I2C_InitStruct->I2C_ClockSpeed * 3));
}
else /*I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_16_9*/
//{
/* Fast mode speed calculate: Tlow/Thigh = 16/9 */
// result = (u16)(pclk1clock / (I2C_InitStruct->I2C_ClockSpeed * 25));
/* Set DUTY bit */
/* result |= I2C_DutyCycle_16_9;
}
/* Test if CCR value is under 0x1*/
/* if ((result & CCR_CCR_Set) == 0)
{
/* Set minimum allowed value */
/* result |= (u16)0x0001;
}
/* Set speed value and set F/S bit for fast mode */
/*tmpreg |= result | CCR_FS_Set;
/* Set Maximum Rise Time: ((300/(1000000000/pclk1clock))+1 */
/* I2Cx->TRISE = (u16)(((freqrange * 300) / 1000) + 1);
}
/* Write to I2Cx CCR */
//I2Cx->CCR = tmpreg;
/* Enable I2Cx */
//I2C_Cmd(I2Cx, ENABLE);
/*---------------------------- I2Cx CR1 Configuration ------------------------*/
/* Get the I2Cx CR1 value */
// tmpreg = I2Cx->CR1;
/* Clear ACK, SMBTYPE and SMBUS bits */
//tmpreg &= CR1_CLEAR_Mask;
/* Configure I2Cx: mode and acknowledgement */
/* Set SMBTYPE and SMBUS bits according to I2C_Mode value */
/* Set ACK bit according to I2C_Ack value */
// tmpreg |= (u16)((u32)I2C_InitStruct->I2C_Mode | I2C_InitStruct->I2C_Ack);
/* Write to I2Cx CR1 */
// I2Cx->CR1 = tmpreg;
/*---------------------------- I2Cx OAR1 Configuration -----------------------*/
/* Set I2Cx Own Address1 and acknowledged address */
///I2Cx->OAR1 = (I2C_InitStruct->I2C_AcknowledgedAddress | I2C_InitStruct->I2C_OwnAddress1);
//}*/
/*********************************************************************************
Function Name:I2C_Start( )
Function:This function will be used by the master to generate a start signal
Parameter:I2C_TypeDef *I2C1:The target I2C controllor->
Return:none
Note:Setting the START bit causes the interface to generate a Start condition and to switch to
Master mode (M/SL bit set) when the BUSY bit is cleared(BUSY: Bus Busy,Set by hardware on
detection of SDA or SCL low,cleared by hardware on detection of a Stop condition.).
**********************************************************************************/
void I2C_Start(void)
{
I2C1->CR1 = 0x0401 ;
I2C1->CR1 |= 0x0100 ; //Set START bit to generate a start condition->
while((!(I2C1->SR1&0x0001))); //Wait for start condition generation finishment.Or, the peripheral enter master mode(M/SL bit set.).
}
/**********************************************************************************************************************************************
Function Name:Address_Sending( )
Function:To send the slave address->
Parameter:u8 Dataphase_Mode:Reciver or Transmitter
u8 AddressHeader :In 10_bit address mode ,here is the address header->
u8 Low_Address :The address to be sent in 7_bit address mode or the lower 8 bits address to be sent in 10_bit address mode->
u8 Addring_Mode :Addring_Mode_10 to indicate here is a 10_bit address or Addring_Mode_7 to indicate here is a 7_bit address->
I2C_TypeDef I2C1:The target I2C controllor->
Return:none
Note:
*********************************************************************************************************************************************/
void Address_Sending(u8 Dataphase_Mode,u8 AddressHeader,u8 Low_Address,u8 Addring_Mode)
{
if(Addring_Mode==Addring_Mode_10)
{
I2C1->DR=AddressHeader;
while(!(I2C1->SR1&0x0008));
I2C1->DR=Low_Address;
if(Dataphase_Mode==Reciver)
{
while (!(I2C1->SR1&0x0002));
I2C_Start();
I2C1->DR = AddressHeader;
}
}else
{
if(Dataphase_Mode==Reciver)
{
Low_Address |= 0x01;
I2C1->DR = Low_Address; //Send the slave address with LSB set->
while(!(I2C1->SR1&0x0002)) ; //Wait till the ADDR bit set->Clear the ADDR bit by read SR1 followed by a DR read or write.
while((I2C1->SR2 &0x0004)) ;
}else
{
Low_Address &= 0xFE;
I2C1->DR = Low_Address; //Send the slave address with LSB reset->
while(!(I2C1->SR1&0x0002)) ; //Wait till the ADDR bit set->Clear the ADDR bit by read SR1 followed by a DR read or write.
while(!(I2C1->SR2&0x0004)) ;
}
}
}
/****************************************************************************************
Function Name:I2C_ReciveByte( )
Function:To process the reciption of a byte->
Parameter:none
Return: u8 RecivedByte:The recived byte->
I2C_TypeDef *I2C1:The target I2C controllor->
Note:
****************************************************************************************/
u8 I2C_ReciveByte(void)
{
while (!( I2C1->SR1&0x0040)) ; //Wail for RxNE set , indicates that a byte has been recived successfully-> // So, read ou the recived byte to ready for use->
return I2C1->DR;
}
/****************************************************************************************
Function Name:I2C_SendByte( )
Function:To send a byte of data->
Parameter: u8 ByteToSend
I2C_TypeDef *I2C1:The target I2C controllor->
Return:none
Note:
****************************************************************************************/
void I2C_SendByte(u8 ByteToSend)
{
I2C1->DR=ByteToSend; //Write a byte to the DR to ready for sending->
while (!( I2C1->SR1&0x0080)); //Wait till TxE set indicates that the byte sent finisheed successfully->
}
/**********************************************************************************************************************************************
Function Name:I2C_SendBlock( )
Function:To send a data block->
Parameter: u8 *BlockToSend:The address of the first byte of the block to be sent->
u8 Total_Btyes :The size of the block in byte->
I2C_TypeDef *I2C1 :The target I2C controllor->
Return:none
Note:
*********************************************************************************************************************************************/
void I2C_SendBlock(u8 *BlockToSend,u8 Total_Bytes)
{
I2C1->DR=*BlockToSend; //Write a byte to the DR to ready for senting->
BlockToSend++; //Point to the next to be sent byte->
Total_Bytes--; //Total of the bytes to be sent decriment by 1->
while (Total_Bytes) //If all the bytes have been sent,than continue->
{
if(I2C1->SR1&0x0080) //TxE set indicates that the byte sent finisheed successfully->
{
I2C1->DR=*BlockToSend; //So , write anther byte to the DR to ready for senting->
BlockToSend++; //Point to the next to be sent byte->
Total_Bytes--; //Total of the bytes to be sent decriment by 1->
}
}
}
/**************************************************************************************
Function Name:I2C_Stop()
Function:This function will be used by the master to generate a stop signal of the transmittion
Parameter:I2C_TypeDef *I2C1:The target I2C controllor->
Return:none
Note:
****************************************************************************************/
void I2C_Stop_Write(void)
{
while(!( I2C1->SR1&0x0080)); //Wait till the last byte sent succesfully->
I2C1->CR1 |=0x0200 ; //Set STOP bit to generate a start condition->
}
void I2C_Stop_Read(void)
{
/* Send I2C1 STOP Condition */
while(!( I2C1->SR1&0x0040)); //Wait till the last byte sent succesfully->
I2C1->CR1 |=0x0200 ;
}
/**********************************************************************************************************************************************
Function Name:Recive_Data_From_A_slave()
Function:To send the slave address->
Parameter:u8 AddressHeader :In 10_bit address mode ,here is the address header->
u8 Low_Address :The address to be sent in 7_bit address mode or the lower 8 bits address to be sent in 10_bit address mode->
u8 Addring_Mode :Addring_Mode_10 to indicate here is a 10_bit address or Addring_Mode_7 to indicate here is a 7_bit address->
u8 *Buffer :The recived data buffer address->
u8 Total :The total number of bytes to be recived from a slave->
Return:u8 ERR_Flag :The erro type if occured ->
Note:
*********************************************************************************************************************************************/
u8 Recive_Data_From_A_slave(u8 *Buffer,u8 Total,u8 Header,u8 Low_Address,u8 Addring_Mode)
{
u8 ERR_Flag=0;
I2C_MasterIni();
I2C_Start();
Address_Sending(Reciver,Header,Low_Address,Addring_Mode);
while(Total>1)
{
*Buffer=I2C_ReciveByte();
Buffer++;
Total--;
}
I2C_Stop_Read(); //Set the stop bit wright after the second last byte recived successfully,to generate a stop condition after the last byte reciption->
*Buffer=I2C_ReciveByte(); //Recive the last byte->
return ERR_Flag;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -