标题:
我的单片机+iic程序怎么读写不了? 搞了好几天搞不明白
[打印本页]
作者:
YANGTAIHUAN
时间:
2022-3-11 19:41
标题:
我的单片机+iic程序怎么读写不了? 搞了好几天搞不明白
求求大佬们看看哪出问题了,1602模块没问题 仿真里读出来的是一个黑块
at24c02.c
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCK = P1^3;
sbit SDA = P1^4;
void Delayms(uint x);
void Delayus(uchar x);
void Delay5us();
void Delay5ms();
void init(){
SCK = 1;
_nop_();_nop_();_nop_();
SDA = 1;
_nop_();_nop_();_nop_();
}
void start(){
SCK = 1;
_nop_();_nop_();_nop_();
SDA = 1;
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
SDA = 0;
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
SCK = 0;
}
void stop(){
SCK =1;
SDA = 0;
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
SDA = 1;
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
SDA = 0;
SCK = 0;
}
void WaitAck(){
uchar i = 0;
SDA = 1;
SCK = 1;
Delayus(5);
while(SDA == 1 && (i < 250))
i++;
SCK = 0;
_nop_(), _nop_(), _nop_();
}
//void react(){
// SCK = 0;
// SDA = 1;
// SDA = 0;
// SCK = 1;
// _nop_();_nop_();_nop_();
// _nop_();_nop_();_nop_();
// SCK = 0;
// SDA = 1;
//}
void noack(){
SDA=1;
_nop_();_nop_();_nop_();
SCK=1;
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
SCK=0;
_nop_();_nop_();_nop_();
SDA = 0;
}
uchar readByte(){
uchar i, k = 0;
for(i = 0; i < 8; i++){
SCK = 0;
k <<= 1;
Delay5us();
if(SDA == 1){
k |= 0x01;
}
SCK = 0;
Delay5us();
}
_nop_();
Delay5ms();
return k;
}
void writeByte(uchar dat){
uchar i = 0;
for(i = 0; i < 8; i++){
SCK = 0;
Delay5us();
SDA = dat & 0x80;
_nop_();_nop_();_nop_();_nop_();
SCK = 1;
Delay5us();
dat <<= 1;
}
SCK = 0;
_nop_();_nop_();_nop_();
Delay5ms();
}
void addByte(uchar wordAddress, uchar dat){
start();
writeByte(0xa0);
WaitAck();
writeByte(wordAddress);
WaitAck();
writeByte(dat);
WaitAck();
stop();
Delayms(5);
}
uchar readAddByta(uchar wordAddress){
uchar dat;
start();
writeByte(0xa0);
WaitAck();
writeByte(wordAddress);
WaitAck();
stop();
start();
writeByte(0xa1);
WaitAck();
dat = readByte();
noack();
stop();
return dat;
}
void Delayms(uint x){
int i, j;
for(i = x; i > 0; --i){
for(j = 110; j > 0; --j);
}
}
void Delayus(uchar x){
while(x--);
}
void Delay5us() //@12.000MHz
{
_nop_();
}
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 10;
j = 183;
do
{
while (--j);
} while (--i);
}
复制代码
main.c
#include <reg52.h>
#include <intrins.h>
#include "at24c02.h"
#include "proteus_1602.h"
#define uchar unsigned char
#define uint unsigned int
sbit SCK = P1^3;
sbit SDA = P1^4;
void main(){
Delayms(2000);
while(1){
uchar temp = 0;
init();
init_1602();
addByte(0x00, 0x00);
Delayms(10);
temp = readAddByta(0x00);
writeData_1602(temp + 0x38);
Delayms(50);
}
}
复制代码
作者:
YANGTAIHUAN
时间:
2022-3-11 19:42
1602模块没问题 仿真里读出来的是一个黑块
作者:
tatachaoren
时间:
2022-3-12 02:56
IIC的时序很重要,最好尝试的用逻辑分析仪读一下时序,看看是不是时序出现问题,还有如果时序没问题的话,要看时间,比如起始信号,一高一低时间会不会太短,导致从机识别不了IIC的起始信号等等。
作者:
lkc8210
时间:
2022-3-12 08:09
要贴就贴全一点
为什么不把at24c02.h/proteus_1602.h/proteus_1602.c也贴上来?
void WaitAck(){
uchar i = 0;
SDA =
0
;
SCK = 1;
Delayus(5);
while(SDA == 1 && (i < 250))
i++;
SCK = 0;
_nop_(), _nop_(), _nop_();
}
作者:
wolfinn
时间:
2022-3-13 10:53
读写两句间加个延时看看,器件两个动作要有间隔的。
作者:
Lxy18
时间:
2022-3-13 11:56
iic通信和晶振频率24c02的地址都有关系,错一点都可能导致通信失败。
分享一下自用的驱动程序,仅供参考。
晶振12MHz或者11.0592MHz,24c02的3个地址全接地。
at24c02.c
#include "at24c02.h"
#include "delay.h"
//IIC启动
void Start(void)
{
SDA1=1;
Delay_Us(2);
SCL1=1;
Delay_Us(2);//建立时间是SDA保持时间>4.7us
SDA1=0;
Delay_Us(2);//保持时间是>4us
SCL1=0;
Delay_Us(2);
}
//IIC停止
void Stop(void)
{
SDA1=0;
Delay_Us(2);
SCL1=1;
Delay_Us(2);//建立时间大于4.7us
SDA1=1;
Delay_Us(4);
}
//IIC发送字节
//dat:要发送的字节
void Send_Byte(unsigned char dat)
{
unsigned char a=0,b=0;
for(a=0;a<8;a++)//要发送8位,从最高位开始
{
SDA1=dat>>7; //起始信号之后SCL=0,所以可以直接改变SDA信号
dat=dat<<1;
Delay_Us(2);
SCL1=1;
Delay_Us(2);//建立时间>4.7us
SCL1=0;
Delay_Us(2);//时间大于4us
}
}
//IIC检查应答
bit Check_Ack(void)
{
//unsigned char t;
SCL1=0;
SDA1=1;
Delay_Us(2);
SCL1=1;
Delay_Us(2);
CY=SDA1;
SCL1=0;
Delay_Us(2);
return(CY);
}
//IIC应答
void Ack(void)
{
SDA1=0; //EEPROM通过在收到每个地址或数据之后
SCL1=1; //置SDA低电平的方式确认表示收到读SDA口状态
Delay_Us(1);
SCL1=0;
Delay_Us(1);
SDA1=1;
}
//IIC无应答
void NoAck(void)
{
SDA1=1;
SCL1=1;
Delay_Us(1);
SCL1=0;
}
//IIC接收字节
unsigned char Receive_Byte(void)
{
unsigned char a=0,dat=0;
SDA1=1; //起始和发送一个字节之后SCL都是0
Delay_Us(2);
for(a=0;a<8;a++)//接收8个字节
{
SCL1=1;
Delay_Us(2);
dat<<=1;
dat|=SDA1;
Delay_Us(2);
SCL1=0;
Delay_Us(2);
}
return dat;
}
//At24cxx读写数据
//addr:要读/写数据的地址
//*dat:要读/写的数据
//length;数据的长度
//RW:1:写,0:读
void At24c02_RW(unsigned char addr,unsigned char *dat,unsigned char length,bit RW)
{
Start();
Send_Byte(0xa0);//发送写器件地址
Check_Ack();
Send_Byte((unsigned char)addr);//发送要写入内存地址
Check_Ack();
if(RW) //写
{ while(length--)
{
Send_Byte(*dat++);
Check_Ack();
}
}
else
{
Start();
Send_Byte(0xa1);
Check_Ack();
while(--length)
{
*dat++=Receive_Byte();
Ack();
}
*dat=Receive_Byte();//读取最后一个字节
NoAck();
}
Stop();
if(RW)
Delay_Us(1000);
}
复制代码
at24c02.h
#ifndef __AT24C02_H__
#define __AT24C02_H__
#include<reg52.h>
sbit SCL1=P2^1;
sbit SDA1=P2^0;
void Start(void);
void Stop(void);
bit Check_Ack(void);
void Ack(void);
void NoAck(void);
void Send_Byte(unsigned char dat);
unsigned char Receive_Byte(void);
void At24c02_RW(unsigned char addr,unsigned char *dat,unsigned char length,bit RW);
#endif
复制代码
delay.c
#include "delay.h"
/*******************************************************************************
* 函 数 名 : Delay_Us()
* 函数功能 : 延时1us
* 输 入 : i
* 输 出 : 无
*******************************************************************************/
void Delay_Us(int i)
{
while(i--);
}
/*******************************************************************************
* 函 数 名 : Delay_Ms()
* 函数功能 : 延时1Ms
* 输 入 : m
* 输 出 : 无
*******************************************************************************/
void Delay_Ms(int m)
{
while(m--)
{
Delay_Us(125);
}
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1