各位帮忙看哈,我这个程序那里有问题,咋就是不通啊?
#include <stm32f10x_lib.h>
#include "24c02.h"
#include "delay.h"
#include "sys.h"
#define SCL_0 PCout(12)=0
#define SCL_1 PCout(12)=1
#define SDA_0 PCout(11)=0
#define SDA_1 PCout(11)=1
#define SDA_value PCin(11)
#define SCL_OUT() {GPIOC->CRH&=0xfff0ffff;GPIOC->CRH |=0x00030000;}//SCL线设为输出
#define SDA_OUT() {GPIOC->CRH&=0xffff0fff;GPIOC->CRH |=0x00003000;}//SDA线设为输出
#define SDA_IN() {GPIOC->CRH&=0xffff0fff;GPIOC->CRH |=0x00008000;}//SDA线设为输入
void Init_24c02(void)//24c02接口初始化
{
SCL_OUT();
SDA_OUT();
SCL_1;
SDA_1;
delay_ms(10);
}
void start(void) //开始信号(由时序图看出,scl线为高电平,sda线由高到低跳变为开始信号)
{
SDA_OUT();//SDA线设为输出
SCL_OUT();//SCL线设为输出
SDA_1;//sda=1
delay_us(10);
SCL_1;//scl=1
delay_us(10);
SDA_0;//sda=0,sda从高电平->低电平,起始信号
//SCL_0;//scl=0,scl线处于被占用状态
delay_us(10);
}
void stop(void) //终止信号(由时序图看出,scl线为高电平,sda线由低到高跳变为停止信号)
{
SDA_OUT();//SDA线设为输出
SCL_OUT();//SCL线设为输出
SDA_0;
SCL_0;
delay_us(10);
SDA_1; //sda=1,sda从低电平->高电平,终止信号
delay_us(10);
SCL_1;
delay_us(10);
}
void ack(void) //应答信号
{
u8 i=0;
SCL_OUT();
SDA_IN(); //SDA设为输入
SCL_1;
delay_us(10);
while(( SDA_value==1)&&(i<250))i++;;//sda=0,已经应答;或者延时一段时间后,默认为已经应答
SCL_0; //应答后,拉低时钟线,使其处于被占用的状态
delay_us(10);
}
void noack(void) //非应答信号(可以不写)
{
SDA_OUT();//SDA设为输出
SDA_1;
delay_us(10);
SCL_1;
delay_us(10);
SCL_0; //scl有变化时,sda保持不变,即非应答
delay_us(10);
}
void iicwr_byte(u8 dat)//写入一个字节
{
u8 i;
SDA_OUT();//SDA线输出
SCL_OUT();//SCL线输出
SCL_0; //只有在时钟线上的信号为低电平时,数据线上的高电平或低电平才允许变化
//(时钟线为高电平时,才能进行读写;
//也就是说读写数据时,必须将SCL拉高,然后送入或读出数据,完毕后,再将SCL拉低)
delay_us(10);
for(i=0;i<8;i++)
{
if(dat&0x80)//首先传输的是数据的最高位(MSB)
{
SDA_1;//sda=1;
}
else
{
SDA_0;//sda=0;
}
SCL_1; //scl=1;(上升沿写入数据)时钟线为高电平时,才能进行读写
delay_us(10);
SCL_0; //scl=0;(为下次上升沿的来临做准备)只有在时钟线上的信号为低电平时,据线上的高电平或低电平才允许变化
delay_us(10);
dat=dat<<1;//移位
delay_us(10);
}
SDA_1; //sda=1; //数据线释放;
delay_us(10);
}
u8 iicre_byte(void) //读一个字节
{
u8 i,dat;
SDA_OUT();//SDA输出
SCL_OUT();
SCL_0; //scl=0;
delay_us(10);
SDA_1; //sda=1; //数据线释放
delay_us(10);
for(i=0;i<8;i++)
{
SCL_1;//scl=1; //时钟线为高电平时,才能进行读写
delay_us(10);
dat=dat<<1;//判断8次,移位7次
SDA_IN();//SDA输入
if(SDA_value)
{
dat++;//自增,个位加1
}
SCL_0;//scl=0;数据才能改变
delay_us(10);
}
return dat;
}
void write(u8 address,u8 dat)//写操作(需要地址和数据)
{
//Init_24c02(); //初始化
start();
iicwr_byte(0xa0);//写器件地址(a是地址固定部分,0的前三位是选择位,第四位0为写;若第四位为1,则是读;)
ack();
iicwr_byte(address);//写器件内部存储器地址
ack();
iicwr_byte(dat);//数据
ack();
stop();
}
u8 read(u8 address) //读操作(需要地址)
{
u8 dat;
//Init_24c02(); //初始化
start();
iicwr_byte(0xa0);//寻址(地址位1010000+0)//低位为0,即写
ack();
iicwr_byte(address);
ack();
start();//因为是读数据,所以需重复发起始信号
iicwr_byte(0xa1);//寻址(地址位1010000+1)//低位为1,即读
ack();
dat=iicre_byte();//读出的给dat
stop();
return dat;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "stm32f10x_lib.h"
#include "delay.h"
#include "usart.h"
#include "sys.h"
#include "24c02.h"
int main(void)
{
Stm32_Clock_Init(9); //时钟初始化
delay_init(72);
JTAG_Set(0x02);//关闭JTAG和SWD接口,使相关IO口,能作为普通IO口使用
while(1)
{
RCC->APB2ENR |=(1<<4);//GPIOC口时钟打开
RCC->APB2ENR |=(1<<3);//GPIOB口时钟打开
GPIOB->CRL =0x33333333;//GPIOA.0~GPIOA.7设为输出
Init_24c02();//24c02接口初始化
write(7,0x55);//向第7个地址写入数据0x55
delay_ms(20);
GPIOB->ODR=read(7);//读取地址7的数据
delay_ms(20);
}
}
|