打印
[STM32F1]

模拟IIC

[复制链接]
621|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
邪乎风云|  楼主 | 2020-9-9 10:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 邪乎风云 于 2020-9-9 12:23 编辑

为了后面使用模拟的IIC,特地封装了一下,仅供参考
代码里边的标记单词f l g被和谐了,这是什么情况

使用特权

评论回复
沙发
邪乎风云|  楼主 | 2020-9-9 10:44 | 只看该作者
头文件 V_IIC.h

#ifndef __V_IIC_H
#define __V_IIC_H
typedef struct{
        unsigned char  (*SDA_Read)(void);
        void (*SDA_Out)(unsigned char state);
        void (*SCL_Out)(unsigned char state);
        void (*SDA_DirSet)(unsigned char out);
}V_IIC_MasterHandle;       
#define USE_OS 1 //是否使用操作系统
#if USE_OS
#include "ucos_ii.h"
#include "os_cpu.h"
#include "os_cfg.h"
#define OS_IIC_Dealyms(t)  OSTimeDlyHMSM(0,t/1000/60,t/1000%60,t%1000); //操作系统延时函数
extern unsigned char ucos_start_**;
#define os_start_** ucos_start_** //操作系统启动标志
#define os_protect_start_no_change OSSchedLock //关闭调度
#define os_protect_end_no_change OSSchedUnlock //重启调度
#endif
typedef   unsigned char AdrType;//寄存器数据类型 一个字节或多个字节
/*******
master IIC的句柄
SDA_Read SDA数据引脚作为输入状态读取引脚电平的函数指针,返回1表示高电平
SDA_Out  SDA数据引脚作为输出状态输出引脚电平的函数指针,state为1表示输出高电平
SCL_Out  SCL时钟引脚作为输出状态输出引脚电平的函数指针,state为1表示输出高电平
SDA_DirSet SDA数据引脚输入输出状态的切换的函数指针,out为1表示SDA数据引脚设为输出状态
******/
void V_Master_IIC_Init(V_IIC_MasterHandle *master,unsigned char  (*SDA_Read)(void),void (*SDA_Out)(unsigned char state),void (*SCL_Out)(unsigned char state),void (*SDA_DirSet)(unsigned char out));
/****************
master IIC的句柄
slave_adr 从机地址7bit的
adr 寄存器起始地址
redata 读取的数据内容,指针是输出用的
len 读取数据长度

返回 4 成功
*****************/
unsigned char  V_Master_IIC_Read(V_IIC_MasterHandle *master,unsigned char slave_adr,AdrType adr,char *redata,unsigned short len);

/****************
master IIC的句柄
slave_adr 从机地址7bit的
adr 寄存器起始地址
data 写入数据的数据内容,指针是输入使用
len 写入数据长度

返回 4 成功
*****************/
unsigned char  V_Master_IIC_Write(V_IIC_MasterHandle *master,unsigned char slave_adr,AdrType adr,char *data,unsigned short len);

void IIC_delay_us(unsigned int t);//根据需要修改,可重新定义,此处非操作系统的延时

#endif

使用特权

评论回复
板凳
邪乎风云|  楼主 | 2020-9-9 10:45 | 只看该作者
本帖最后由 邪乎风云 于 2020-9-9 10:57 编辑

c文件
#include "V_IIC.h"
//#include "stdio.h"

__attribute__((weak)) void IIC_delay_us(unsigned int t)
{
  unsigned int i =0;
        for(i=0;i<t;i++){
        }
}

void V_Master_IIC_Init(V_IIC_MasterHandle *master,unsigned char (*SDA_Read)(void),void (*SDA_Out)(unsigned char state),void (*SCL_Out)(unsigned char state),void (*SDA_DirSet)(unsigned char out))
{
        master->SCL_Out = SCL_Out;
        master->SDA_Out = SDA_Out;
        master->SDA_Read = SDA_Read;
        master->SDA_DirSet = SDA_DirSet;
}

void V_Master_IIC_Start(V_IIC_MasterHandle *master)
{
        master->SDA_DirSet(1);
        master->SDA_Out(1);
        master->SCL_Out(1);
        IIC_delay_us(4);
        master->SDA_Out(0);
        IIC_delay_us(4);
        master->SCL_Out(0);
}        

void V_Master_IIC_Stop(V_IIC_MasterHandle *master)
{        
        master->SDA_DirSet(1);
        master->SCL_Out(0);
        master->SDA_Out(0);
        IIC_delay_us(4);
        master->SCL_Out(1);
        IIC_delay_us(2);
        master->SDA_Out(1);
        IIC_delay_us(4);
}        
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
unsigned char V_Master_IIC_Wait_Ack(V_IIC_MasterHandle *master)
{
        unsigned char ucErrTime=0;
        master->SDA_DirSet(0);
        master->SDA_Out(1);
        IIC_delay_us(1);           
        master->SCL_Out(1);
        IIC_delay_us(1);         
        while(master->SDA_Read())
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        V_Master_IIC_Stop(master);
                        return 1;
                }
        }
        master->SCL_Out(0);           
        return 0;  
}

void  V_Master_IIC_Ack(V_IIC_MasterHandle *master)
{
        master->SCL_Out(0);        
        master->SDA_DirSet(1);
        master->SDA_Out(0);
        IIC_delay_us(2);
        master->SCL_Out(1);        
        IIC_delay_us(2);
        master->SCL_Out(0);        
}
//不产生ACK应答                    
void V_Master_IIC_NAck(V_IIC_MasterHandle *master)
{
        master->SCL_Out(0);        
        master->SDA_DirSet(1);
        master->SDA_Out(1);
        IIC_delay_us(2);
        master->SCL_Out(1);        
        IIC_delay_us(2);
        master->SCL_Out(0);        
}                        

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答                          
void V_Master_IIC_Send_Byte(V_IIC_MasterHandle *master,unsigned char txd)
{                        
    unsigned char t;        
    master->SCL_Out(0);
                master->SDA_DirSet(1);
    for(t=0;t<8;t++)
    {              
        master->SDA_Out((txd&0x80)>>7);
        txd<<=1;           
                                IIC_delay_us(2);   //对TEA5767这三个延时都是必须的
                                master->SCL_Out(1);
                                IIC_delay_us(2);
                                master->SCL_Out(0);
                                IIC_delay_us(2);
    }         
}            
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
unsigned char V_Master_IIC_Read_Byte(V_IIC_MasterHandle *master,unsigned char ack)
{
        unsigned char i,receive=0;
        master->SDA_DirSet(0);
  for(i=0;i<8;i++ )
        {
        master->SCL_Out(0);
        IIC_delay_us(2);
                                master->SCL_Out(1);
        receive<<=1;
        if(master->SDA_Read())receive++;   
                                IIC_delay_us(1);
  }                                         
        if (!ack)
                        V_Master_IIC_NAck(master);//发送nACK
        else
                        V_Master_IIC_Ack(master); //发送ACK   
        return receive;
}



unsigned char  V_Master_IIC_Read(V_IIC_MasterHandle *master,unsigned char slave_adr,AdrType adr,char *redata,unsigned short len)
{
        unsigned short i =0;
        unsigned char result = 0;
#if USE_OS
        if(os_start_**){
                os_protect_start_no_change();
        }
#endif
        V_Master_IIC_Stop(master);
        V_Master_IIC_Start(master);
        V_Master_IIC_Send_Byte(master,slave_adr<<1);
        if(V_Master_IIC_Wait_Ack(master)){
                result= 1;
                goto IIC_Read_End;
        }
        for(i=0;i<sizeof(AdrType);i++){
                V_Master_IIC_Send_Byte(master,adr>>((sizeof(AdrType)-i-1)*8));
                if(V_Master_IIC_Wait_Ack(master)){
                        result= 2;
                        goto IIC_Read_End;
                }
        }
        V_Master_IIC_Start(master);
        V_Master_IIC_Send_Byte(master,(slave_adr<<1) +1);
        if(V_Master_IIC_Wait_Ack(master)){
                result = 3;
                goto IIC_Read_End;
        }
        for(i=0;i<len;i++){
                if( i ==(len -1)){
                        *redata++=V_Master_IIC_Read_Byte(master,0);
                }else{
                        *redata++=V_Master_IIC_Read_Byte(master,1);
                }
        }
        V_Master_IIC_Stop(master);
        result=4;
        goto IIC_Read_End;
        IIC_Read_End:
#if USE_OS
        if(os_start_**){
                os_protect_end_no_change();
        }        
#endif        
        return result;
}
unsigned char V_Master_IIC_Write(V_IIC_MasterHandle *master,unsigned char slave_adr,AdrType adr,char *data,unsigned short len)
{
        unsigned short i =0;
        unsigned char result = 0;
#if USE_OS
        if(os_start_**){
                os_protect_start_no_change();
        }        
#endif
        V_Master_IIC_Stop(master);
        V_Master_IIC_Start(master);
        V_Master_IIC_Send_Byte(master,slave_adr<<1);
        if(V_Master_IIC_Wait_Ack(master)){
                result= 1;
                goto IIC_Write_End;
        }
        for(i=0;i<sizeof(AdrType);i++){
               
                V_Master_IIC_Send_Byte(master,adr>>((sizeof(AdrType)-i-1)*8));
                if(V_Master_IIC_Wait_Ack(master)){
                        result = 2;
                        goto IIC_Write_End;
                }        
        }
        for(i=0;i<len;i++){
                V_Master_IIC_Send_Byte(master,*data++);
                if(V_Master_IIC_Wait_Ack(master)){
                        result= 3;
                        goto IIC_Write_End;
                }
        }
        V_Master_IIC_Stop(master);
        
        result= 4;
        goto IIC_Write_End;
IIC_Write_End:
#if USE_OS
        if(os_start_**){
                os_protect_end_no_change();
                OS_IIC_Dealyms(10*len);
        }else{
                IIC_delay_us(10000*len);
        }
#else        
        IIC_delay_us(10000*len);
#endif        
        return result;
}





















使用特权

评论回复
地板
邪乎风云|  楼主 | 2020-9-9 10:59 | 只看该作者
源代码附件

V_IIC.zip

2.4 KB

使用特权

评论回复
5
稳稳の幸福| | 2020-9-9 20:33 | 只看该作者
粘贴到代码专用框里就OK了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

21

帖子

1

粉丝