求助关于GPIO模拟IIC通讯的问题

2019-07-20 23:42发布

我用原子个模拟的IIC程序能够读取我的芯片值,但是我换个IO口模拟就会出现读不出数据或者OXFF!这是什么情况?我只是换了端口


//#define SDA_IN()  {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}
//#define SDA_OUT() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}
//#define SCL_OUT() {GPIOB->CRH&=0XFFFFF0FF;GPIOB->CRH|=3<<8;}
#define SCL_OUT() {GPIOB->CRH&=0XFFF0FFFF;GPIOB->CRH|=3<<16;}
#define SDA_IN()  {GPIOB->CRH&=0X0FFFFFFF;GPIOB->CRH|=8<<20;}
#define SDA_OUT() {GPIOB->CRH&=0X0FFFFFFF;GPIOB->CRH|=3<<20;}




//#define SDA_IN()  {GPIOB->CRH&=~(0XF<<(3*4));GPIOB->CRH|=8<<3*4;}
//#define SDA_OUT() {GPIOB->CRH&=~(0XF<<(3*4));GPIOB->CRH|=3<<3*4;}
//#define SDA_IN()  {GPIOB->CRH&=~(0XF<<(4*4));GPIOB->CRH|=8<<4*4;}
//#define SDA_OUT() {GPIOB->CRH&=~(0XF<<(4*4));GPIOB->CRH|=3<<4*4;}
//IO2ù×÷oˉêy         
/*#define IIC_SCL_SET GPIO_SetBits(GPIOB,GPIO_Pin_10)
#define IIC_SCL_CLR GPIO_ResetBits(GPIOB,GPIO_Pin_10)
#define IIC_SDA_SET GPIO_SetBits(GPIOB,GPIO_Pin_11)
#define IIC_SDA_CLR GPIO_ResetBits(GPIOB,GPIO_Pin_11)
#define READ_SDA   GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) //ê&#228;è&#235;SDA */
#define IIC_SCL_SET GPIO_SetBits(GPIOB,GPIO_Pin_12)
#define IIC_SCL_CLR GPIO_ResetBits(GPIOB,GPIO_Pin_12)
#define IIC_SDA_SET GPIO_SetBits(GPIOB,GPIO_Pin_13)
#define IIC_SDA_CLR GPIO_ResetBits(GPIOB,GPIO_Pin_13)
#define READ_SDA   GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13) //ê&#228;è&#235;SDA

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
15条回答
八度空间
1楼-- · 2019-07-20 23:54
[mw_shl_code=applescript,true]/**
  ***********************************
  *                               模拟IIC通讯驱动
  *
  *                       (C) Copyright 2000-2020, **
  *                             All Rights Reserved
  ***********************************
  *
  * @File    : bsp_iic.c
  * @By      : **
  * @Version : V1.0
  * @Date    : 2015 / 02 / 28
  *
  ***********************************
  *
  *                                   Update
  *
  * @Version : V1.1
  * @By      : **
  * @Date    : 2015 / 10 / 16
  * @Brief   : A、增加对Cortex-CM3和Cortex-CM4内核自动切换支持
  *            B、增加对51平台和ARM平台宏定义
  *            C、修改控制端口,直接修改头文件中的宏定义即可
  *
  ***********************************
**/

#include "bsp_iic.h"

/***********************************
                                 定义变量
***********************************/

#if __USER_System_Platform == 1  //ARM平台
GPIO_InitTypeDef GPIO_InitStructure;
#endif

/**
  ***********************************
  * @Name   : GPIO初始化
  *
  * @Brief  : STM32平台,其他平台请修改或者注释掉
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : none
  ***********************************
**/
void IIC_Init(void)
{
#if __USER_System_Platform == 1  //ARM平台

#if __CORTEX_M == 0x03  //Cortex-CM3
        
        RCC_APB2PeriphClockCmd(RCC_IIC_GPIOx, ENABLE);
        
        GPIO_InitStructure.GPIO_Pin   = SDA_Pin_x | SCL_Pin_x;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
        
#elif __CORTEX_M == 0x04  //Cortex-CM4
        
        RCC_AHB1PeriphClockCmd(RCC_IIC_GPIOx, ENABLE);
        
        GPIO_InitStructure.GPIO_Pin   = SDA_Pin_x | SCL_Pin_x;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
        
#endif
        
        GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);
        
        GPIO_SetBits(IIC_GPIOx, SDA_Pin_x | SCL_Pin_x);  //输出高电平
        
#else  //51平台
        
        IIC_SDA = 1;
        IIC_SCL = 1;
        
#endif
}

#if __USER_System_Platform == 1  //ARM平台
/**
  ***********************************
  * @Name   : GPIO输出方向
  *
  * @Brief  : none
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : none
  ***********************************
**/
void IIC_SDA_OUT(void)
{
#if __CORTEX_M == 0x03  //Cortex-CM3
        
        GPIO_InitStructure.GPIO_Pin   = SDA_Pin_x;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
        
#elif __CORTEX_M == 0x04  //Cortex-CM4
        
        GPIO_InitStructure.GPIO_Pin   = SDA_Pin_x;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
        
#endif
        
        GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);
}

/**
  ***********************************
  * @Name   : GPIO输入方向
  *
  * @Brief  : none
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : none
  ***********************************
**/
void IIC_SDA_IN(void)
{
#if __CORTEX_M == 0x03  //Cortex-CM3
        
        GPIO_InitStructure.GPIO_Pin   = SDA_Pin_x;
//        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
        
#elif __CORTEX_M == 0x04  //Cortex-CM4
        
        GPIO_InitStructure.GPIO_Pin   = SDA_Pin_x;
//        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;
//        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
        
#endif
        
        GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);
}
#endif

/**
  ***********************************
  * @Name   : IIC启动
  *
  * @Brief  : SCL高电平期间,SDA由高电平突变到低电平时启动总线
  *           SCL: __________
  *                          \__________
  *           SDA: _____
  *                     \_______________
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : none
  ***********************************
**/
void IIC_Start(void)
{
#if __USER_System_Platform == 1  //ARM平台
        IIC_SDA_OUT();        //设置成输出
#endif

        IIC_SDA = 1;        //为SDA下降启动做准备
        IIC_SCL = 1;        //在SCL高电平时,SDA为下降沿时候总线启动
        
#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */
        
        IIC_Delay();
        IIC_SDA = 0;        //突变,总线启动
        IIC_Delay();
        IIC_SCL = 0;
        IIC_Delay();

#else  /* 否则不使用延时函数改变通讯频率 */
        
        IIC_SDA = 0;        //突变,总线启动
        IIC_SCL = 0;

#endif  /* end __USER_DELAY_CLK */
}

/**
  ***********************************
  * @Name   : IIC停止
  *
  * @Brief  : SCL高电平期间,SDA由低电平突变到高电平时停止总线
  *           SCL: ____________________
  *                          __________
  *           SDA: _________/
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : none
  ***********************************
**/
void IIC_Stop(void)
{
#if __USER_System_Platform == 1  //ARM平台
        IIC_SDA_OUT();        //设置成输出
#endif

        IIC_SDA = 0;        //为SDA上升做准备
        
#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */

        IIC_Delay();
        IIC_SCL = 1;        //在SCL高电平时,SDA为上升沿时候总线停止
        IIC_Delay();
        IIC_SDA = 1;        //突变,总线停止
        IIC_Delay();

#else  /* 否则不使用延时函数改变通讯频率 */

        IIC_SCL = 1;        //在SCL高电平时,SDA为上升沿时候总线停止
        IIC_SDA = 1;        //突变,总线停止

#endif  /* end __USER_DELAY_CLK */
}

/**
  ***********************************
  * @Name   : 主机向从机发送应答信号
  *
  * @Brief  : none
  *
  * @Input  : a:应答信号
  *           0:应答信号
  *           1:非应答信号
  *
  * @Output : none
  *
  * @Return : none
  ***********************************
**/
void IIC_Ack(u8 a)
{
#if __USER_System_Platform == 1  //ARM平台
        IIC_SDA_OUT();        //设置成输出
#endif

        if(a)        IIC_SDA = 1;        //放上应答信号电平
        else        IIC_SDA = 0;
        
#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */

        IIC_Delay();
        IIC_SCL = 1;        //为SCL下降做准备
        IIC_Delay();
        IIC_SCL = 0;        //突变,将应答信号发送过去
        IIC_Delay();

#else  /* 否则不使用延时函数改变通讯频率 */

        IIC_SCL = 1;        //为SCL下降做准备
        IIC_SCL = 0;        //突变,将应答信号发送过去

#endif  /* end __USER_DELAY_CLK */
}

/**
  ***********************************
  * @Name   : 向IIC总线发送一个字节数据
  *
  * @Brief  : none
  *
  * @Input  : dat:要发送的数据
  *
  * @Output : none
  *
  * @Return : ack:返回应答信号
  ***********************************
**/
u8 IIC_Write_Byte(u8 dat)
{
        u8 i=0;
        u8 ErrTime=0;
//        u8 iic_ack=0;        //iic应答标志
        
#if __USER_System_Platform == 1  //ARM平台
        IIC_SDA_OUT();        //设置成输出
#endif

        for(i = 0;i < 8;i++)
        {
                if(dat & 0x80)        IIC_SDA = 1;        //判断发送位,先发送高位
                else        IIC_SDA = 0;

#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */
                        
                IIC_Delay();
                IIC_SCL = 1;        //为SCL下降做准备
                IIC_Delay();
                IIC_SCL = 0;        //突变,将数据位发送过去
                dat<<=1;        //数据左移一位
        }        //字节发送完成,开始接收应答信号

        IIC_SDA = 1;        //释放数据线
        
#if __USER_System_Platform == 1  //ARM平台
        IIC_SDA_IN();        //设置成输入
#endif
        
        IIC_Delay();
        IIC_SCL = 1;        //为SCL下降做准备
        IIC_Delay();

#else  /* 否则不使用延时函数改变通讯频率 */

                IIC_SCL = 1;        //为SCL下降做准备
                IIC_SCL = 0;        //突变,将数据位发送过去
                dat<<=1;        //数据左移一位
        }        //字节发送完成,开始接收应答信号

        IIC_SDA = 1;        //释放数据线
        
#if __USER_System_Platform == 1  //ARM平台
        IIC_SDA_IN();        //设置成输入
#endif
        
        IIC_SCL = 1;        //为SCL下降做准备

#endif  /* end __USER_DELAY_CLK */
        
//        iic_ack |= IN_SDA;        //读入应答位
        while(IN_SDA)
        {
                ErrTime++;
                if(ErrTime > 230)
                {
                        IIC_Stop();
                        return 1;  //非应答
                }
        }
        IIC_SCL = 0;
        return 0;
//        return iic_ack;        //返回应答信号
}

/**
  ***********************************
  * @Name   : 从IIC总线上读取一个字节数据
  *
  * @Brief  : none
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : 读取到的数据
  ***********************************
**/
u8 IIC_Read_Byte(void)
{
        u8 i=0;
        u8 x=0;

        IIC_SDA = 1;        //首先置数据线为高电平
        
#if __USER_System_Platform == 1  //ARM平台
        IIC_SDA_IN();        //设置成输入
#endif
        
        for(i = 0;i < 8;i++)
        {
                x <<= 1;        //读入数据,高位在前

#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */

                IIC_Delay();
                IIC_SCL = 1;        //突变
                IIC_Delay();
               
                if(IN_SDA)        x |= 0x01;        //收到高电平

                IIC_SCL = 0;
                IIC_Delay();
        }        //数据接收完成

#else  /* 否则不使用延时函数改变通讯频率 */

                IIC_SCL = 1;        //突变
               
                if(IN_SDA)        x |= 0x01;        //收到高电平

                IIC_SCL = 0;
        }        //数据接收完成

#endif  /* end __USER_DELAY_CLK */

        IIC_SCL = 0;

        return x;        //返回读取到的数据
}
[/mw_shl_code]


自己看
沉默焚烧
2楼-- · 2019-07-21 00:06
 精彩回答 2  元偷偷看……
Rocks
3楼-- · 2019-07-21 03:08
如果你原本程式都不改 只要改端口
那變數名稱你也不能動

像是原本
#define SCL_OUT()

那你能動的是後面的參數{GPIOB->CRH&=0XFFF0FFFF;GPIOB->CRH|=3<<16;}

而不是你另外去宣告不同參數名稱

另外你要用兩組IIC模擬 變數名稱也要不同
wtdwll1000
4楼-- · 2019-07-21 06:28
 精彩回答 2  元偷偷看……
wtdwll1000
5楼-- · 2019-07-21 10:18
本帖最后由 wtdwll1000 于 2015-12-28 11:53 编辑






















































Rocks
6楼-- · 2019-07-21 11:51
http://www.openedv.com/posts/list/17451.htm

同問

有些數值要跟著改動

暫存器操作看得我頭疼 你自己對照手冊吧

一周热门 更多>