查看: 1160|回复: 0
打印 上一主题 下一主题

stm8s IIC从机,简单可用版代码

[复制链接]
跳转到指定楼层
沙发
发表于 2016-3-29 12:21:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
官方IIC从机实在用不到,经过本人研究,写了个简单可通讯的从机版本。现在发出来分享下。


从机程序:
uchar u8_My_Buffer[8];   //存储要发送的值
/***IIC初始化****/
void Init_I2C (void)
{
        I2C_CR1 =0x81;//关闭时钟延展,启动IIC
        I2C_CR2=0x04;
        I2C_FREQR=1;
        I2C_OARL=0xa0;//设备地址
        
        I2C_OARH=0x40;
        
        I2C_ITR=0x06;
        
        
}

/***********IIC中断服务函数*********************/
@far @interrupt void I2C_Slave_check_event(void)
{

        static uchar sr1;                                       
        static uchar sr2;
        static uchar sr3;
        uchar tsr1,tsr2,tsr3;
        

if(I2C_SR1_ADDR)     // 地址匹配
{
  uchar erro=8;
        iict=0;
        I2C_DR=u8_My_Buffer[0];
        tsr1=I2C_SR1;
        tsr3=I2C_SR3;
        iict++;
        while(I2C_SR1_BTF&(erro--));
}
if(I2C_SR1_TXE)      //继续发送数据
{
        uchar erro=8;
        I2C_DR=u8_My_Buffer[iict++];
        while(I2C_SR1_BTF&(erro--));
}
if(I2C_SR2_AF)
{
        I2C_SR2 &= ~I2C_SR2_AF;
}


}
/*******************************************************/


主机读取数据(模拟):

@near uchar iictemp[7];//存储读取到的数据

void SDA_out(void)   //配置SDA引脚为输出

{

        PB_DDR|=0x20;//PB5

        PB_CR1|=0x20;//推挽输出

        PB_CR2&=0xdf;        

}

void SDA_in(void)   //配置SDA引脚为输入

{

        PB_DDR&=0xdf;//PB5

        PB_CR1|=0x20;//上拉输入

        PB_CR2&=0xdf;        

}

void SCL_out(void)  //配置SCL引脚为输出

{

        PB_DDR|=0x10;//PB4

        PB_CR1|=0x10;//推挽输出

        PB_CR2&=0xef;        

}

void SCL_in(void)   //配置SCL引脚为输入

{

        PB_DDR&=0xef;//PB5

        PB_CR1|=0x10;//上拉输入

        PB_CR2&=0xef;        

}




/*起始条件*/
void Start(void)
{
        SCL_out();
        SDA_out();
        SCL=1;
        SDA=1;
        Delay_us(1);
        SDA=0;
        Delay_us(1);
        SCL=0;
}        
/*停止条件*/
void Stop(void)
{
        SDA_out();
        SDA=0;
        Delay_us(1);
        SCL=1;
        Delay_us(1);
        SDA=1;
}

void IIC_w(uchar Idata)  //写一个字节
{
        uchar iici;
                for(iici=0;iici<8;iici++)
        {
                SCL=0;
                Delay_us(1);
                if(Idata&0x80)
                SDA=1;
                else
                SDA=0;
                Delay_us(1);
                SCL=1;
                Idata<<=1;
                Delay_us(1);
        }
        SCL=0;
}

void IIC_r(uchar* Idata)  //读一个字节
{
        uchar iici;
        SDA=1;
        SDA_in();
         for(iici=0;iici<8;iici++)
  {
                SCL=1;
                Delay_us(1);
                *Idata<<=1;
                if(SDAI)
                *Idata|=1;
                else
                *Idata|=0;
                Delay_us(1);
                SCL=0;
                Delay_us(1);
        }
}

void I2C_Send_Ack(void) //发送ACK
{
        SDA=0;
        SDA_out();
        SCL=0;
        Delay_us(1);
        SDA=0;
        Delay_us(1);
        SCL=1;
        Delay_us(1);
        SCL=0;
        }
        
unsigned char I2C_Get_Ack(void)  //读取ACK
{
        uchar ack;
        SDA=1;
        SDA_in();
        Delay_us(1);
        SCL=1;
        ack=SDAI;
        Delay_us(1);
        SCL=0;
        SDA_out();
        return ack;
        
}


void IICdata_Read(void)  //调用该函数会读取到从机数据
{
        uchar i;
        Start();
        
        IIC_w(0xa1);
        if(I2C_Get_Ack())
        {
                Stop();
                return;
        }
        
        for(i=0;i<8;i++)
        {
                Delay_us(1);
                IIC_r(&iictemp);
                if(i<7)                    //这里很重要,最后一位不发送ACK,自动停止通讯
                I2C_Send_Ack();
        }
        Stop();
}



该程序存在较少的误码,加上校验位后可以稳定的通讯。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

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