九齐MCU io口模拟I2C
Posted logicexpression
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了九齐MCU io口模拟I2C相关的知识,希望对你有一定的参考价值。
IO口模拟I2C的要点:
- 数据帧符合标准的I2C协议
- 分的清楚ACK与NACK的区别,是那个设备下拉。
- 数据位时间符合要求
项目合作开发,吹牛扯蛋、交朋友 ,请联系:18665321219
#include "iic_p.h"
#include <ny8.h>
#include "main.h"
#include <ny8_constant.h>
#include <stdint.h>
#define sda_out() iosTA=(IOSTA & ((uint8_t)(~ C_PA6_Input))) //输出
#define sda_in() IOSTA=(IOSTA | C_PA6_Input) //输入
#define sda PORTAbits.PA6 //sda输出高
#define scl PORTAbits.PA4 //scl输出高,写程序注意默认让其保持高电平
void delayus(uint8_t tim)
{
while(tim--) //2.4us周期 clk_8M
{
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
}
}
void i2c_stop(void)
{
scl = 0;
delayus(1);
sda = 0;
sda_out();
delayus(2);
scl = 1;
delayus(1);
sda = 1;
}
void i2c_start(void)
{
sda = 1; //
delayus(1);
scl = 1; //发送停止位后将SCL及SDA置位
delayus(1);
sda = 0;
delayus(1);
}
//测试ok
void trandata(uint8_t data)
{
//IOSTB=(IOSTB & ((uint8_t)(~ C_PB2_Input))); //输出
uint8_t i;
//scl = 0;
for( i = 0;i<8;i++ )
{
scl = 0;
delayus(1);
if((data & 0x80) == 0x80)
{
sda = 1;
}
else
{
sda = 0;
}
data <<=1;
delayus(2);
scl = 1;
delayus(3);
}
//scl = 0;
//delayus(3);
//sda = 0; //因该把IO输出禁止,不然slaver无法下拉
}
//测试ok
void revdata(uint8_t *data)
{
uint8_t i;
//sda_in();
for(i=0;i<8;i++)
{
scl = 0;
delayus(3);
scl = 1;
delayus(1);
*data <<= 1;
if(sda==1)
{
*data |= 0x01; //首位置为一
}
else
{
*data &= 0xfe;
}
delayus(2);
}
}
//测试ok
void i2c_nack(void)
{
scl = 0;
delayus(1);
sda = 1;
sda_out();
delayus(2);
scl = 1;
delayus(3);
}
//测试ok
uint8_t i2c_dectack(void)
{
uint8_t ackflg;
scl = 0;
delayus(1);
sda_in();
delayus(2);
scl = 1;
delayus(1);
if(sda ==1)
{
ackflg = 0; //为接收到应答
}
else
{
ackflg = 1; //接收到应答
}
delayus(2);
return ackflg;
}
//测试ok 3ms
uint8_t i2c_wtdata(uint8_t address,uint8_t data)
{
uint8_t temp,errflg=0;
i2c_start();
temp = 0xa0; //地址位赋值1010add(R/W)
trandata(temp);
if(i2c_dectack() == 0)
{
errflg = 1; //未接收到应答数据
}
scl = 0;
delayus(1);
sda = 1;
sda_out();
temp = address;
trandata(temp);
if(i2c_dectack() == 0)
{
errflg = 1; //未接收到应答数据
}
scl = 0;
delayus(1);
sda = 1;
sda_out();
trandata(data);
if(i2c_dectack() == 0)
{
errflg = 1; //未接收到应答数据
}
// scl = 0;
// delayus(3);
// sda = 0;
// sda_out();
i2c_stop();
return errflg;
}
//测试ok //测试不稳定
uint8_t curddata(uint8_t *data)
{
uint8_t temp,errflg=0;
i2c_start();
temp = 0xa1; //地址位赋值1010add(R/W)
trandata(temp);
if(i2c_dectack() == 0)
{
errflg = 1; //未接收到应答数据
}
//sda_out();
revdata(data);
i2c_nack();
i2c_stop();
return errflg;
}
//测试ok 4ms
uint8_t i2c_rddata(uint8_t address,uint8_t *pdata)
{
uint8_t temp,errflg=0;
i2c_start();
temp = 0xa0; //地址位赋值1010000(R/W)
trandata(temp);
if(i2c_dectack() == 0)
{
errflg = 1; //未接收到应答数据
}
scl = 0;
delayus(1);
sda = 1; //默认为上拉
sda_out();
temp = address;
trandata(temp);
if(i2c_dectack() == 0)
{
errflg = 1; //未接收到应答数据
}
scl = 0;
delayus(1);
sda = 1;
sda_out();
if(curddata(pdata) == 1)
{
errflg = 1;
}
return errflg;
}
/*
//写数据遵守写入读出
void i2cbus_wt(uint8_t address,uint8_t data)
{
uint8_t temp;
do
{
while(i2c_wtdata(address,data) == 1); //写入数据
while(curddata(&temp) == 1); //读出数据
} while(data != temp); //比较通过视为写入成功
}
*/
以上是关于九齐MCU io口模拟I2C的主要内容,如果未能解决你的问题,请参考以下文章