STM32F1 模擬I2C驅動DAC(LTC2605)程式
由於在電路設計上將SCL、SDA線拉太長導致硬體I2C時常出問題,所以考慮用模擬I2C解決,這裡參考別人的程式碼然後自己應用到24位DAC(LTC2605)上,已移植成功。
(1).simulate_i2c.c
#include "stm32f10x.h"
#include "simulate_i2c.h"
#define HIGH 1
#define LOW 0
#define TRUE 1
#define FALSE 0
#define Master_Address 0x0A
#define WR 0X00
#define RD 0X01
#define SCL_H GPIO_SetBits(GPIOB,GPIO_Pin_6)
#define SCL_L GPIO_ResetBits(GPIOB,GPIO_Pin_6)
#define SDA_H GPIO_SetBits(GPIOB,GPIO_Pin_7)
#define SDA_L GPIO_ResetBits(GPIOB,GPIO_Pin_7)
void delay_us(u16 time)
{
u16 i = 0;
while(time--)
{
i = 10;
while(i--);
}
}
void I2C_INIT(void)
{
GPIO_InitTypeDef GPIO_Init_Structure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_Init_Structure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init_Structure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_Init_Structure);
GPIO_SetBits(GPIOB,GPIO_Pin_6);
}
void SDA_OUT(){
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //????
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO????50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void SDA_IN(){
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //????,?????????????
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO????50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void I2C_Start(void)
{
SDA_OUT();
SDA_H;
SCL_H;
delay_us(5);
SDA_L;
delay_us(5);
SCL_L;
}
void I2C_Stop(void)
{
SDA_OUT();
SCL_L;
SDA_L;
delay_us(5);
SCL_H;
SDA_H;
delay_us(5);
}
u8 I2C_Wait_Ack(void)
{
u8 ucErrTime = 0;
SDA_H;
delay_us(5);
SDA_IN();
SCL_H;
delay_us(5);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7))
{
ucErrTime++;
if(ucErrTime > 250)
{
return FALSE;
}
}
SCL_L;
return TRUE;
}
void I2C_Ack(void)
{
SCL_L;
SDA_OUT();
SDA_L;
delay_us(5);
SCL_H;
delay_us(5);
SCL_L;
}
void I2C_NAck(void)
{
SCL_L;
SDA_OUT();
SDA_H;
delay_us(5);
SCL_H;
delay_us(5);
SCL_L;
}
void I2C_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
SCL_L;
for(t = 0; t < 8; t++)
{
if((txd&0x80) >> 7)
SDA_H;
else
SDA_L;
txd <<= 1;
delay_us(5);
SCL_H;
delay_us(5);
SCL_L;
delay_us(5);
}
}
u8 I2C_Read_Byte(void)
{
unsigned char i, receive = 0;
SDA_IN();
for(i = 0; i < 8; i++ )
{
SCL_L;
delay_us(5);
SCL_L;
receive = (receive << 1) | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7);
delay_us(5);
}
return receive;
}
u8 Write_Temp_Value(u16 temp_input)
{
u8 Data[2];
Data[0]= temp_input&0x00ff;
Data[1]= (temp_input>>8)&0x00ff;
I2C_Start();
I2C_Send_Byte(0x20);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(0x22);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(Data[1]);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(Data[0]);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Stop();
return 0;
}
u8 Write_Pre_In(u16 pre_In_input)
{
u8 Data[2];
Data[0]= pre_In_input&0x00ff;
Data[1]= (pre_In_input>>8)&0x00ff;
I2C_Start();
I2C_Send_Byte(0x20);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(0x21);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(Data[1]);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(Data[0]);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Stop();
return 0;
}
u8 Write_Pre_Out(u16 pre_Out_input)
{
u8 Data[2];
Data[0]= pre_Out_input&0x00ff;
Data[1]= (pre_Out_input>>8)&0x00ff;
I2C_Start();
I2C_Send_Byte(0x20);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(0x20);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(Data[1]);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Send_Byte(Data[0]);
if(!I2C_Wait_Ack()){
I2C_Stop();
return 0;
}
I2C_Stop();
return 0;
}
(2). simulate_i2c.h
#ifndef __SIMULATE_I2C_H__
#define __SIMULATE_I2C_H__
#include "stm32f10x.h"
void delay_us(u16 time);
void I2C_INIT(void);
void SDA_OUT();
void SDA_IN();
void I2C_Start(void);
void I2C_Stop(void);
u8 I2C_Wait_Ack(void);
void I2C_Ack(void);
void I2C_NAck(void);
void I2C_Send_Byte(u8 txd);
u8 I2C_Read_Byte(void);
u8 Write_Temp_Value(u16 temp_input);
u8 Write_Pre_In(u16 pre_In_input);
u8 Write_Pre_Out(u16 pre_Out_input);
#endif /* __I2C_DRIVE_MCP_H */
(3). main.c
int main(void){
I2C_INIT();
Write_Temp_Value(65535);
}