历史上的今天
今天是:2024年09月26日(星期四)
2021年09月26日 | 基于IAR开发环境的STM8S模拟IIC代码
2021-09-26 来源:eefocus
基于IAR STM8 2.10开发环境,STM8S005K6单片机,模拟IIC方式读写AT24C16或AT24C32,已验证可以正常对AT24C32进行读写数据,只是有个疑问,对于单片机接SDA脚的IO口进行方向控制反而引起时序不正常而读写不了数据,例程中是将此IO口始终设置为输出,不知道会不会有隐患,有待测试...
以下是代码,完整代码请下载附件,包含完整工程!
#include "24Cxx.h"
#include "stm8s.h"
#include "stm8s_gpio.h"
#define AT24C32_SETSDAIN GPIO_Init(AT24C32_SDA_PORT, GPIO_PIN_6, GPIO_MODE_IN_FL_NO_IT)
#define AT24C32_SETSDAOUT GPIO_Init(AT24C32_SDA_PORT, GPIO_PIN_6, GPIO_MODE_OUT_OD_LOW_SLOW)
#define I2C_SLAW 0xA0 /*器件地址选择及写标志*/
#define I2C_SLAR 0xA1 /*器件地址选择及读标志*/
void nops(void)
{
// asm("nop");
// asm("nop");
uint16_t i = 0;
for (; i < 5; i++);
}
// 总线复位
void I2C_Reset(void)
{
AT24C32_SCL_HIGH;
AT24C32_SDA_HIGH;
}
// I2C操作严重错误
void I2C_Error(void)
{
//复位I2C总线
I2C_Reset();
//进入死循环
while (1)
{
}
}
// 发送起始条件
void I2C_Start_A(void) /*起始条件*/
{
AT24C32_SCL_HIGH;
nops();
AT24C32_SDA_LOW;
nops();
AT24C32_SCL_LOW;
nops();
}
// 停止条件
void I2C_Stop_A(void)
{
AT24C32_SDA_LOW;
nops();
AT24C32_SCL_HIGH;
nops();
AT24C32_SDA_HIGH;
nops();
AT24C32_SCL_LOW;
nops();
}
// 产生一个时钟信号
uint8_t I2C_GenerateClock(void)
{
uint8_t bData = 0;
uint16_t t = 0;
AT24C32_SCL_HIGH;
nops();
for (t = 0; t < 6; t++);
if (AT24C32_READSDA)
{
bData = 1;
}
AT24C32_SCL_LOW;
nops();
return bData;
}
// 应答位
void I2C_Ack(uint8_t bAckYes)
{
if (bAckYes)
{
AT24C32_SDA_LOW;
}
else
{
AT24C32_SDA_HIGH;
}
I2C_GenerateClock();
AT24C32_SDA_HIGH;
}
// 发送数据子程序, ucData为要求发送的数据
uint8_t I2C_Send(uint8_t ucData)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
if (ucData & 0x80)
{
AT24C32_SDA_HIGH;
}
else
{
AT24C32_SDA_LOW;
}
ucData <<= 1;
I2C_GenerateClock();
}
AT24C32_SDA_HIGH;
return (!I2C_GenerateClock());
}
// 读一个字节的数据,并返回该字节值
uint8_t I2C_Read(void)
{
uint8_t ucData = 0;
uint8_t i;
for (i = 0; i < 8; i++)
{
ucData <<= 1;
if (I2C_GenerateClock())
{
ucData |= 1;
}
}
return ucData;
}
// 设置下一步操作的地址(一字节地址)
uint8_t I2C_SetAddress(uint16_t u16Addr)
{
// 发送启动信号
I2C_Start_A();
// 发送访问地址
return (I2C_Send(I2C_SLAW) && I2C_Send(u16Addr));
}
// 设置下一步操作的地址(两字节地址)
uint8_t I2C_SetAddress16(uint16_t u16Addr)
{
// 发送启动信号
I2C_Start_A();
// 发送从器件地址
// 发送访问地址
return (I2C_Send(I2C_SLAW) && I2C_Send(u16Addr >> 8) && I2C_Send(u16Addr & 0xff));
}
// 向8位地址的器件( 如:24C02 )写数据 bAddressIs16bit = 0
// 向16位地址的器件( 如:24C32 )写数据 bAddressIs16bit = 1
void Write_Byte_24c32(uint8_t *pDat, uint16_t u16Addr, uint8_t ucNbyte, uint8_t bAddressIs16bit)
{
uint8_t bWriteError = FALSE; //写数据出错标志位
uint8_t i;
uint8_t ucDataBuf = 0;
uint32_t Cnt = 0;
for (i = 0; i < ucNbyte; i++)
{
if (bAddressIs16bit)
{
if (I2C_SetAddress16(u16Addr + i) == 0)
{
bWriteError = TRUE;
break;
}
}
else
{
if (I2C_SetAddress(u16Addr + i) == 0)
{
bWriteError = TRUE;
break;
}
}
ucDataBuf = *(pDat + i);
if (I2C_Send(ucDataBuf) == 0)
{
bWriteError = TRUE;
break;
}
I2C_Stop_A();
ucDataBuf = 12;
do
{
I2C_Start_A();
} while ((++Cnt < 500000) && I2C_Send(I2C_SLAW) == 0);
//如果50mS内还没有响应,则进入保护性报警状态
if (Cnt == 500000)
{
bWriteError = TRUE;
break;
}
I2C_Stop_A();
}
if (bWriteError)
{
I2C_Error();
}
}
// 从8位地址的器件( 如:24C02 )读数据 bAddressIs16bit = 0
// 从16位地址的器件( 如:24C32 )读数据 bAddressIs16bit = 1
void Read_nByte_24c32(uint8_t *pDat, uint16_t u16Addr, uint8_t ucNbyte, uint8_t bAddressIs16bit)
{
uint8_t bReadError标志寄存器 = FALSE; //读EEPROM错误标志位
史海拾趣
|
原文如下: ◆電池1本時(入力電圧1.5V時) ・3.3V 最大負荷電流 約160mA=効率約81% ・5.0V 最大負荷電流 約70mA ※出力5Vでは電池2本での使用を推奨します。 ◆電池2本時(入力電圧3. ...… 查看全部问答> |
|
程序运行中需要运行 NVIC_SystemReset();这个函数,一旦运行就会死机 没办法单步调试,所以问下大家问题可能出在哪里? 重新上电启动就没有问题。谢谢大家了!… 查看全部问答> |
|
程序编译可以通过,但是rebuid all时会出现错误,如 Reset_VEC B _cy_begin \\"pwm_generate_vec.asm\\", line 7: AN IDENTIF ...… 查看全部问答> |
|
1、我用FET_examples目录中FET140文件夹下,fet140_ta01.c文件组建项目。 2、在iar for msp430 环境中,用软件模拟为什么不能进入定时中断呢? 3、是不是因为没有smclk的原因?在这个环境中如何设置lfx 和x2呢?并并我修改了程序,将 ...… 查看全部问答> |
|
Warning (14130): Reduced register \"current_state[7]~reg0\" with stuck data_in port to stuck value GNDWarning (14130): Reduced register \"current_state[6]~reg0\" with stuck data_in port to stuck value GNDWarning: Converted presett ...… 查看全部问答> |
|
#define uchar unsigned char#define uint unsigned intuchar Page; uchar Col,cc=0,dd=0; bdata char com_data;sbit mos_bit=com_data^7; void wtcom(void); /********************引脚 ...… 查看全部问答> |




