52单片机iic读写c语言,如何52单片机的I2C读写24C08程序问题排查修改
------波形在一樓
isoimg2130老師提供在單片機正常運行的程序:
#include "reg52.h"
#include??"intrins.h"
typedef unsigned char u8;
sbit SCL=P2^1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//I2C??時鐘
sbit SDA=P2^2;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//I2C??數據
void delay()? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//4微秒延時函數
{
_nop_();
_nop_();
_nop_();
_nop_();
}
void yanshi(unsigned int hm)? ?? ?? ?? ?? ?? ?//延時毫秒
{
unsigned int i;
do
{
i = 12000000 / 97560;
while(--i)? ?? ???;
}
while(--hm);
}
void Start_I2c()
{
SDA=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //發送起始條件的數據信號
SCL=1;
delay();
SDA=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //發送起始信號
delay();
SCL=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//鉗住I2C總線,準備發送或接收數據
}
void Stop_I2c()
{
SCL=0;
SDA=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //發送結束條件的數據信號
delay();
SCL=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //結束條件建立時間大于4μs
SDA=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//發送I2C總線結束信號
delay();
}
u8 I2c_wait_ack(void)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //等待應答信號到來? ?? ?? ?1,接收應答失敗 0,接收應答成功
{
u8 Time=0;
SDA=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //準備接收應答位
_nop_();
SCL=1;
_nop_();
while(SDA)
{
Time++;
if(Time>250)
{
Stop_I2c();
return 1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//無應答返回1
}
}
SCL=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//時鐘輸出0
return 0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//有應答返回0
}
void??SendByte(u8??c)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//字節數據發送函數
{
u8??BitCnt;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//條件 一定要開啟總線 保持SCL處于0狀態 才能進行寫入
for(BitCnt=0;BitCnt<8;BitCnt++) //要傳送的數據長度為8位
{
SDA=c<
_nop_();
SCL=1;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //置時鐘線為高,通知被控器開始接收數據位
_nop_();
SCL=0;
_nop_();
}
}
void I2C_Ack(void)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//產生ACK應答
{
SCL=0;
delay();
SDA=1;
delay();
SDA=0;
delay();
SCL=1;
delay();
SCL=0;
delay();
SDA=1;
delay();
}
void I2C_NAck(void)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //不產生ACK應答
{
SCL=0;
delay();
SDA=1;
delay();
SCL=1;
delay();
SCL=0;
delay();
SDA=0;
delay();
}
u8 RcvByte(u8 ack)? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //字節數據接收函數
{? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //ack??1 發送應答??0 不發送應答
u8 retc=0,i;
SDA=1;
delay();
for(i=0;i<8;i++)
{
SCL=0;? ?? ?? ?? ?? ?? ?? ?? ???//置時鐘線為低,準備接收數據位
delay();
SCL=1;? ?? ?? ?? ?? ?? ?? ?? ???//置時鐘線為高使數據線上數據有效
_nop_();
retc<<=1;
if(SDA)retc++;? ?? ?? ?? ?? ?? ?? ? //讀數據位,接收的數據位放入retc中
_nop_();
}
if (!ack)
I2C_NAck();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//發送nACK
else
I2C_Ack();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //發送ACK
return retc;
}
u8 AT24C_Rcvone(u8 Addr)? ?? ?? ?? ?? ?? ?? ?? ?? ?//在AT24CXX指定地址讀出一個數據
{
u8 temp=0;
Start_I2c();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//啟動總線
SendByte(0xa0);? ?? ?? ?? ?? ?? ?? ?? ?? ???//發送寫命令
I2c_wait_ack();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //等待應答
SendByte(Addr);? ?? ?? ?? ?? ?? ?? ?? ?? ???//發送地址
I2c_wait_ack();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //等待應答
Start_I2c();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//重新啟動總線
SendByte(0xa1);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//設置為讀操作
I2c_wait_ack();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //等待應答;
temp=RcvByte(0);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //讀字節? ?? ???非應答
Stop_I2c();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//結束總線
return temp;
}
void AT24C_Sendone(u8 Addr,u8 Data)? ?? ???//在AT24CXX指定地址寫入一個數據? ?? ?? ?此函數只限于 c02-c16
{
Start_I2c();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? //啟動總線
SendByte(0xa0);? ?? ?? ?? ?? ?? ?? ?? ?? ? //發送寫命令
I2c_wait_ack();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//等待應答
SendByte(Addr);? ?? ?? ?? ?? ?? ?? ?? ?? ? //發送地址
I2c_wait_ack();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//等待應答
SendByte(Data);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//發送字節數據
I2c_wait_ack();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//等待應答
Stop_I2c();? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//結束總線
yanshi(10);? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//如果是連續發送字節的時候這個延時很重要 否則將回傳錯
}
void main()
{
AT24C_Sendone(10,0xaa);
P1=AT24C_Rcvone(10);
while(1);
}
下面是書本示例運行沒有讀出數據led燈不亮:
I2C.H
#ifndef __I2C_H__? ?//文件名全部都大寫,首尾各添加2個下劃線”__”
#define __I2C_H__
#include
#define uchar unsigned char
sbit SDA=P2^0;??//24C02芯片SDA引腳位定義
sbit SCL=P2^2;? ?? ?? ?//24C02芯片SCL引腳位定義
void delay();? ?? ?? ?? ???//分別對各函數聲明
void start();
void stop();
void ack();
void nack();
void write_byte(uchar date);
uchar read_byte();
void write_at24c02(uchar address ,uchar date);
uchar read_at24c02(uchar address);
#endif
I2C.c
#include "i2c.h"??//包含i2c.h頭文件,注意自建的頭文件是用雙引號
void delay()? ?//微秒級延時函數
{
;;??//用兩個空語句實現短時間延時,當晶振為11.0592MHz時,約4~5微秒
}
void start() //起始信號
{
SDA=1;
SCL=1;
delay();
SDA=0;
delay();
}
void stop()? ?? ???//終止信號
{
SDA=0;
SCL=1;
delay();
SDA=1;
delay();
}
void ack()? ?? ???//應答信號
{
uchar i;
SCL=1;
delay();
while((SDA==1)&&i<250)i++;
SCL=0;
delay();
}
void nack()? ?? ?? ? //無應答信號
{
SCL=1;
delay();
SDA=1;
SCL=0;
delay();
}
void??write_byte(uchar date) //寫入一個字節到I2C總線
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
SCL=0;
delay();
SDA=CY;
delay();
SCL=1;
}
SCL=0;
delay();
SDA=1;
delay();
}
uchar read_byte() //從I2C讀一個字節
{
uchar i,j,k;
SCL=0;
delay();
for(i=0;i<8;i++)
{
SCL=1;
delay();
j=SDA;
k=(k<<1)|j;
SCL=0;
delay();
}
return k;
}
void wrte_at2402(uchar address,uchar date)//at24c02按字節寫入函數
{
start();
write_byte(0xa0);
ack();
write_byte(address);
ack();
write_byte(date);
ack();
stop();
}
uchar read_dat24c02(uchar address)? ?? ???//對at24c02隨機讀函數
{
uchar date;
start();
write_byte(0xa0);
ack();
write_byte(address);
ack();
start();
write_byte(0xa1);
ack();
date=read_byte();
nack();
stop();
return date;
}
main.c
#include
#include"I2C.h"
#include
void delay_10ms()
{
uchar a,b;
for(a=50;a>0;a--)
for(b=200;b>0;b--) ;
}
void main()
{
start();
write_at24c02(10,0xaa);
delay_10ms();
P1=read_at24c02(10);
while(1);
}
總結
以上是生活随笔為你收集整理的52单片机iic读写c语言,如何52单片机的I2C读写24C08程序问题排查修改的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言100以内奇数的和为多少,编写C#
- 下一篇: 怎么用c语言写一个贪吃蛇,刚学C语言,想