历史上的今天
今天是:2024年11月11日(星期一)
2019年11月11日 | STM8 I/O口模拟I2C
2019-11-11 来源:eefocus
STM8I/O口模拟I2C所读数据不正确
STM8 I/O口模拟I2C
#define I2C_ERR 0
#define I2C_CRR 1
#define I2CDataIn 1
#define I2CDataOut 0
#define I2C_PORT (GPIOC)
#define I2CSCL (GPIO_PIN_7)
#define I2CSDA (GPIO_PIN_6)
//***************************************************************
// I2C Data input/output
// 0-Output, 1-Input
//***************************************************************
void I2CDataInOut(bool InOut)
{
if(InOut)
{
GPIO_Init(I2C_PORT,I2CSDA,GPIO_MODE_IN_FL_NO_IT);
}
else
{
GPIO_Init(I2C_PORT,I2CSDA,GPIO_MODE_OUT_OD_LOW_FAST);
}
}
//***************************************************************
// Send start condition
// ensure data is high then issue a start condition
// see also i2c_Start() macro
//***************************************************************
void I2C_Start (void)
{
GPIO_WriteHigh(I2C_PORT, I2CSDA);
_delay_5us(5);
GPIO_WriteHigh(I2C_PORT, I2CSCL);
_delay_5us(5);
GPIO_WriteLow(I2C_PORT, I2CSDA);
_delay_5us(5);
}
//***************************************************************
// Send stop condition
// data low-high while clock high
//***************************************************************
void I2C_Stop (void)
{
GPIO_WriteLow(I2C_PORT, I2CSDA);
_delay_5us(5);
GPIO_WriteHigh(I2C_PORT, I2CSCL);
_delay_5us(5);
GPIO_WriteHigh(I2C_PORT, I2CSDA);
}
//***************************************************************
//ROUTINE NAME : I2C_Ack
//INPUT/OUTPUT : None.
//DESCRIPTION : Acknoledge generation from now.
//COMMENTS : Transfer sequence = DATA, ACK.
//***************************************************************
void I2C_Rack(void)
{
GPIO_WriteLow(I2C_PORT, I2CSDA);
_delay_5us(5);
GPIO_WriteHigh(I2C_PORT, I2CSCL);
_delay_5us(5);
GPIO_WriteLow(I2C_PORT, I2CSCL);
_delay_5us(5);
}
//***************************************************************
//ROUTINE NAME : I2C_nAck
//INPUT/OUTPUT : None.
//DESCRIPTION : Non acknoledge generation from now.
//COMMENTS : Transfer sequence = DATA, NACK.
//***************************************************************
void I2C_nAck (void)
{
GPIO_WriteHigh(I2C_PORT, I2CSDA);
_delay_5us(5);
GPIO_WriteHigh(I2C_PORT, I2CSCL);
_delay_5us(5);
GPIO_WriteLow(I2C_PORT, I2CSCL);
_delay_5us(5);
}
//***************************************************************
// Send a byte to the slave 写一个数据没有应答
// return I2C_ERR OR I2C_CRR
//***************************************************************
bool SendByte(UCHAR I2cData)
{
UCHAR i;
bool I2CStatus;
for(i=0; i<8; i++)
{
GPIO_WriteLow(I2C_PORT, I2CSCL);
_delay_5us(5);
if(I2cData & 0x80)
{GPIO_WriteHigh(I2C_PORT, I2CSDA);}
else
{GPIO_WriteLow(I2C_PORT, I2CSDA);}
GPIO_WriteHigh(I2C_PORT, I2CSCL);
_delay_5us(5);
I2cData <<= 1;
}
GPIO_WriteLow(I2C_PORT, I2CSCL);
GPIO_WriteHigh(I2C_PORT, I2CSDA);//发送完一字节,接收应答
I2CDataInOut(I2CDataIn);
GPIO_WriteHigh(I2C_PORT, I2CSCL);
_delay_5us(5);
if(GPIO_ReadInputPin(I2C_PORT,I2CSDA) == 0)
{
I2CStatus = I2C_CRR;
}
else
{
I2CStatus = I2C_ERR;
}
I2CDataInOut(I2CDataOut);
return I2CStatus;
}
//***************************************************************
//ROUTINE NAME : I2Cm_RxData
//INPUT/OUTPUT : Last byte to receive flag (active high)/Received data byte.
//DESCRIPTION : Receive a data byte.
//COMMENTS : Transfer sequence = DATA, ACK, EV7...
//***************************************************************
UCHAR RcvByte(void)
{
UCHAR i;
UCHAR ReadByte=0;
GPIO_WriteHigh(I2C_PORT, I2CSDA);
I2CDataInOut(I2CDataIn);
_delay_5us(10);
for(i=0; i<8; i++)
{
ReadByte <<= 1;
GPIO_WriteLow(I2C_PORT, I2CSCL);
_delay_5us(5);
GPIO_WriteHigh(I2C_PORT, I2CSCL);
_delay_5us(5);
if(GPIO_ReadInputPin(I2C_PORT,I2CSDA) == 1)
{ReadByte |= 0x01;}
_delay_5us(5);
}
GPIO_WriteLow(I2C_PORT, I2CSCL);
I2CDataInOut(I2CDataOut);
_delay_5us(10);
return ReadByte;
}
/*******************************************************
读N个数据,参数:?
wrDAdr: write device-address 写器件地址??
wordAdr: word address 读数据的寄存器地址??
rdDAdr: read device-address 读器件地址
*pRdDat: p->read data 读数据指针
num: number 需要读数据的个数
*******************************************************/
bool I2C_Read(UCHAR wrDAdr,UCHAR wordAdr,UCHAR *pRdDat,UCHAR num)
{
bool I2CAck;
UCHAR i=0;
UCHAR rdDAdr;
rdDAdr = wrDAdr+1; //读器件地址为写地址加1
I2C_Start(); /*启动I2C*/
_delay_5us(5);
I2CAck = SendByte(wrDAdr); /*发写器件地址*/
if(!I2CAck)
{
return I2C_ERR;
}
I2CAck = SendByte(wordAdr); /*发寄存器地址*/
if(!I2CAck)
{
return I2C_ERR;
}
I2C_Start(); /*重启I2C*/
I2CAck = SendByte(rdDAdr); /*发读器件地址*/
if(!I2CAck)
{
return I2C_ERR;
}
_delay_5us(5);
for(i=0;i { *(pRdDat+i) = RcvByte(); I2C_Rack(); } if(i==num-1) { *(pRdDat+i) = RcvByte(); I2C_nAck(); } I2C_Stop(); return I2C_CRR; } /******************************************************* 写N个数据,前N-1个要应答,最后一个不要应答 wrDAdr: write device-address 写器件地址?? wordAdr: word address 写数据的寄存器地址? *pWrDat: p->write data 写数据指针 num: number 需要写入的数据个数 *******************************************************/ bool I2C_Write(UCHAR wrDAdr,UCHAR wordAdr,UCHAR *pWrDat,UCHAR num) { bool I2CAck; unsigned char i; I2C_Start(); /*启动I2C*/ _delay_5us(5); I2CAck = SendByte(wrDAdr); /*发写器件地址*/ if(!I2CAck) { return I2C_ERR; } I2CAck = SendByte(wordAdr); /*发要写的寄存器地址*/ if(!I2CAck) {
史海拾趣
|
static BOOL SetFrequencyControl1( PDEVICE_INSTANCE DeviceInstance, MASK *Mask ) { ULONG Tmp; EnterCriticalSection(&D ...… 查看全部问答> |
|
我全部用的是MAXIM的器件,虽然做工不太讲究,大家参考看下,本来图应明天上的,因为我手机线在单位,我现把柯达相机要回照了下,要不得明天啦,现在我上传,焊工不好的地方请大家包含,这也是我用一天时间调后半部分,前半部昨晚已结束。 ...… 查看全部问答> |
|
最近看了一些关于RTC校准的帖子,发现很多人存在疑惑。正好最近我也在STM32中实现了RTC校准。发些心得。这些对老手来说有些罗索,但对新手有益处。 实现RTC 校准的核心之一是库文件Stm321f0x_bkp.c中的void BKP_SetRTCCalibrationValue (uint8_t C ...… 查看全部问答> |
|
信号干扰问题已经成为电路设计中几乎不可避免的问题。本人是做智能家居产品设计的,使用无线传输数据,信号干扰(尤其是串扰)在数字设计中普遍存在,有可能出现在芯片、PCB板、连接器、电源和连接器电缆等器件上。如果串扰超过一定的限度就会降低 ...… 查看全部问答> |
|
运放作为比较器,采用0~5V的LM324单电源供电,负脚接的是+2.5V直流电位,正脚接±8V信号。不知道为何,当-8V输入时,输出仍然是+5V。… 查看全部问答> |
|
最在ubuntu下搭建交叉编译环境时,按照附录的步骤搭建,但并不顺利: 首先在Linux系统下建立目录如:/opt/toolchains/目录,再通过WinSCP软件把开发板提供的软件包拷贝到我们刚新建的目录下,然后解压: liunx@ubuntu:/opt/toolchains$ ...… 查看全部问答> |




