历史上的今天
今天是:2024年11月11日(星期一)
2019年11月11日 | STM8S003的GPIO模拟I2C切换输入输出的解决办法
2019-11-11 来源:eefocus
刚开始学STM8,很多东西刚了解,正在做一个温湿度显示小板,就是使用I2C驱动SHT20传感器,并显示到数码管,数码管用的四位一体共阴数码管,STM8管脚有限,添加了一片TM1650做驱动,不过SHT20和TM1650都是用的I2C接口,由于对STM8硬件I2C还不了解,先打算用软件模拟,这就涉及到需要对GPIO做输入输出切换处理来检测ACK响应,刚开始,直接操作DDR寄存器,但是出现从输出切换到输入就会出现单片机死机,不解,查资料,得到一个解决办法,在输出状态时,可以不用切换到输入,我使用管脚D4,D5这两个管脚,这两个管脚比较特殊,就是真正开漏,在管脚描述为T,其它描述为HS(高吸收电流)。
解决办法,将IO设置为开漏输出,外部加上拉,做输入使用之前先输出高,再读取IO状态,即可,附上I2C代码:
#include "swiic.h"
void Delay_us(uint8_t i) //nus 粗略延时
{
for(; i>0; i--)
{
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
/*================================================================
【 Name 】void I2CInit(void)
【Function】I2C初始化,空闲状态
【 Notes 】
【 Author 】Jack
【 Data 】2012.08.07
================================================================*/
void I2CInit(void)
{
SDA = 1;
Delay_us(5);
SCL = 1;
Delay_us(5);
}
void I2CStart(void) //开始信号
{
SCL = 1;
SDA = 1;
Delay_us(5);
SDA = 0;
Delay_us(5);
}
void I2CStop(void) //停止信号
{
Delay_us(5);
SCL = 1;
SDA = 0;
Delay_us(5);
SDA = 1;
}
uint8_t I2Cask(void) //ACK信号
{
uint8_t timeout = 1;
SCL = 1;
SDA = 1; //输入之前先输出高
Delay_us(5);
while((SDA_IN)&&(timeout<=100))
{
timeout++;
}
Delay_us(5);
SCL = 0;
Delay_us(5);
if(timeout >= 100)return NACK;
else return ACK;
}
void I2CWrByte(uint8_t Byte) //写一个字节高位在前,低位在后
{
uint8_t i;
SCL = 0;
Delay_us(1);
for(i=0;i<8;i++)
{
if(Byte&0x80)
{
SDA = 1;
}else
{
SDA = 0;
}
Byte <<= 1;
SCL = 0;
Delay_us(5);
SCL = 1;
Delay_us(5);
SCL = 0;
Delay_us(5);
}
Delay_us(5);
}
/*================================================================
【 Name 】uchar I2CRdByte(uchar AckValue)
【Function】I2C读一个字节数据,入口参数用于控制应答状态,ACK或者NACK
【 Notes 】从高到低,依次接收
【 Author 】dingshidong
【 Data 】2012.08.07
================================================================*/
uint8_t I2CRdByte(uint8_t AckValue)//receivebyte
{
uint8_t i,RDByte=0;
SCL = 0; //置时钟线为低,准备接收数据位--ZLG
SDA = 1; //输入之前先输出高
Delay_us(2);
for (i=0;i<8;i++)
{
SCL = 1; //SCL高电平期间,采集SDA信号,并作为有效数据 //置时钟线为高使数据线上数据有效--ZLG
Delay_us(2);
RDByte <<= 1; //移位
if(SDA_IN==1) //采样获取数据
{
RDByte |= 0x01;
}
else
{
RDByte &= 0xfe;
}
Delay_us(5);
SCL = 0; //下降沿,从机给出下一位值
Delay_us(5);
}
/*以下是I2C总线发送应答信号ACK或者NACK*/
if(1==AckValue) //应答状态
{
SDA = 1;
}
else
{
SDA = 0;
}
Delay_us(3);
SCL = 1;
Delay_us(5); //时钟低电平周期大于4μs--ZLG
SCL = 0; //清时钟线,钳住I2C总线以便继续接收--ZLG
Delay_us(15);
return RDByte;
}
上一篇:STM8 I2C从机
史海拾趣
|
急需!!! 电子技术研发设计开发方案!!! 急需!!! 方案!!! 公司拓展,急需方案,请拥有方案或部分技术的公司和个人迅速与我联系, 邮箱 rdeasy@yahoo.cn 请注明公司全名或个人的姓,详细准确的联系方式和方案,否则不予考。 ...… 查看全部问答> |
|
我做一个232的通讯,希望传一个16进制数比如0XFE到PC,然后PC端通过DELPHI写的程序能读出这个16进制数.哪位有这个例子,PC端怎么读(是通过自己写程序,还是有现成的调试工具)我到现在还不知道呢,哪位讲下啊… 查看全部问答> |
|
控制一组红绿黄灯,通过反复检测开关S1、S2,要求由S1、S2 的“闭合”和“断开”控制红、 绿、黄3灯的点亮。 当S1断,S2断时,黄灯亮; 当S1断,S2合时,绿灯亮; 当S1合,S2断时,红灯闪亮,闪烁周期为2s; 当S1合,S2合时,红灯亮。 要求:1 ...… 查看全部问答> |
|
就我个人经历,大家在无线选型上常会有的一些误区: 1,通信速率,比如很多公司是这样宣传的NRF2401速率是1MBPS, 但,实际上这只是发射速率,而实际真正完成一次发送速率需要涉及到具体的功能,因为功能越复杂,完成一次数据采集的 ...… 查看全部问答> |
|
所有板子的大集合,现在共有40多块,全部手工焊接哦。。 相关教程将会陆续发布 [ 本帖最后由 youki12345 于 2011-12-7 21:57 编辑 ]… 查看全部问答> |




