找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 804|回复: 7
收起左侧

STC15F2K60S2单片机加TMTM1637驱动数码管 检测应答错误

[复制链接]
ID:961122 发表于 2023-2-19 11:00 | 显示全部楼层 |阅读模式
程序如下:问题:当我用多个_nop_()做延时,LED2灯就会亮(我用LED检测应答,如果单片机没收到应签就亮起),数码管显示正常。如果延时用for语句,for内就一个_nop_(),LED2灯就不会亮,数码管也正常。不知为什么,请高人指点。

I2C_DRIVE.C

I2C_DRIVE.C

#define _I2C_DRIVE_C

#include "reg51.h"
#include "I2C_drive.h"
#include "INTRINS.H"

sbit SCL          =                   P2^0 ;                //???????IIC???????
sbit SDA          =                   P2^1 ;                //???????IIC????????

void I2C_delay(void)                                        //延时4us 在11059200时钟下一个nop为1us
{
uint8 i;
//不用for语句用_nop();LED2会亮起,说明检测应答有误
//_nop_();
//_nop_();
//_nop_();
//_nop_();

for(i=0;i<1;i++){   
    _nop_();
}

}

void I2C_Init(void)//IIC初始化
{
//  P2M1 |= 0x03;      //P1.5、P1.6定义为输出
//  P2M0 |= 0x03;   
}

//***********************************************************************************
//*名称:i2c_send_noack()                                                              *
//*功能:无应答I2C总线                                                              *
//*参数:无                                                                         *
//*返回:1 有NOACK信号 0 无NOACK信号                                                 *
//***********************************************************************************
void send_noack(void){
    SDA=1;  //SDA = 1; NO ACK
    I2C_delay();
    SCL=1;  //SCL = 1;
    I2C_delay();
    SCL=0;  //SCL = 0;  //START
}
// iic 应答  for slaver
void send_ack(void) {
    SDA=0; //OUT 0 ACK
    I2C_delay();
    SCL=1;
    I2C_delay();
    SCL=0;
}

/*
*停止iic
*/
void I2C_stop(void){
    SDA=0;
    SCL=0;  //SCL = 0;
    I2C_delay();
    SCL=1;  //SCL = 1;  STOP
    I2C_delay();
    SDA=1;  //SDA = 1;
    I2C_delay();
}

/*
* 启动iic
*/
//  static void start(void) {
void I2C_start(void){

    SDA=1;  //SDA = 1;
    SCL=1;  //SCL = 1;
    I2C_delay();
    SDA=0;  //SDA = 0;
    I2C_delay();
    SCL=0;  //SCL = 0;  //START
}

/*
* iic写一个字节
*/
void I2C_write(uint8 datIn) {
    uint8 mask;
    for(mask = 0x01; mask != 0;mask <<= 1){ // 先写高低为:(mask = 0x80; mask != 0;mask >>= 1) TM1637先写低位
        if((mask & datIn) == 0)
            SDA = 0;
        else
            SDA = 1;
        I2C_delay();
        SCL = 1;
        I2C_delay();
        SCL = 0;
    }
}
uint8 check_ack(void) {
    uint8 ack_flag;

    SDA = 1;
    I2C_delay();
    SCL = 1;    //read ask begin
    I2C_delay();

    ack_flag=SDA;
    I2C_delay();
    SCL = 0;    //read ask end
    return (~ack_flag); //应答值取反以符合通常的逻辑:0=不存在或忙或写入失败,1=存在且空闲或写入成功
}

/*
* iic读一个字节
*/
uint8 I2C_read(void) {
    uint8 mask,dat;
    SDA =1 ;

    for(mask = 0x80; mask != 0;mask >>= 1){
        I2C_delay();
        SCL = 1;
        if(SDA == 0)
            dat &= ~mask;
        else
            dat |= mask;
        I2C_delay();
        SCL = 0;
    }
    return dat;
}




//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

MAIN.C
#include "REG51.H"
#include "I2C_drive.h"
sbit LED0   = P1^0;  
sbit LED1   = P1^1;
sbit LED2   = P1^2;
sbit LED3   = P1^3;

void main(){
  uint8 i;


  I2C_start();
  I2C_write(0x40);
  if(~check_ack()) LED0=0;
  I2C_stop();
  I2C_start();
  I2C_write(0xC0);
  if(~check_ack()) LED1=0;
  for(i=0;i<4;i++){
    I2C_write(0xff);
    if(~check_ack()) LED2=0;
  }
  I2C_stop();
  I2C_start();
  I2C_write(0x8f);
   if(~check_ack()) LED3=0;
  I2C_stop();

  while (1);
}

回复

使用道具 举报

ID:213173 发表于 2023-2-19 13:48 | 显示全部楼层
STC15F2K60S2是1T单片机,一个_nop_()延时时间在12MHz晶振12T单片机是1us,换了运行环境就大相径庭了。
回复

使用道具 举报

ID:961122 发表于 2023-2-19 14:02 | 显示全部楼层
都是在同一个芯片上运行的
回复

使用道具 举报

ID:1063483 发表于 2023-2-19 20:36 | 显示全部楼层
void I2C_delay(void)                                        //延时4us 在11059200时钟下一个nop为1us
{
uint8 i;
//不用for语句用_nop();LED2会亮起,说明检测应答有误
//_nop_();
//_nop_();
//_nop_();
//_nop_();

for(i=0;i<3;i++){   
    _nop_();
}

把for(i=0;i<1;i++)中的   i<1,改为  i<3,  循环4次,应该可以. 并不是一个_nop_()不行,而是单片机就算响应了,数码管来不及响应就过了,试试看吧
回复

使用道具 举报

ID:161164 发表于 2023-2-19 21:04 | 显示全部楼层
以下仿真用12Mhz开始时间:75.25us

2023-02-19_184910.png

运行For之后:78.75us, 耗时:3.5us
2023-02-19_184920.png

运行nop之后:79.92us, 耗时:1.17us
2023-02-19_184929.png


用nop延时的时间太短
不足以让1637返回Ack(拉低电平)
但1637收到命令和数据
所以也可以正常显示
回复

使用道具 举报

ID:961122 发表于 2023-2-20 13:43 | 显示全部楼层
lkc8210 发表于 2023-2-19 21:04
以下仿真用12Mhz开始时间:75.25us

感谢各位,受教了。不但知道了结果,也了解了分析问题的方法。严谨性值得佩服!
回复

使用道具 举报

ID:961122 发表于 2023-2-21 21:16 | 显示全部楼层
用USBee测了4个nop的延时,高电平延时只有2us不到,不知为什么?
a.jpg
回复

使用道具 举报

ID:961122 发表于 2023-2-21 21:19 | 显示全部楼层
用usbee测了一下,SCL高电平中延时了2us不到,同一个延时为什么低电平有6us。真不知为什么?

aa

aa
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表