feixiang20 发表于 2018-8-10 00:04
指针和中断有问题吗,加一个看看呢
IIC_Stop(); //产生一个停止条件
delay_ms(10);...
delay_ms(10);这个是单独写的还是keil里自带的啊
huangyanga 发表于 2018-8-9 18:22
data_buff=I2C_ReceiveData(I2C1);
---------确定这样写可以?整数赋给一个指针了
可以,确定,能读取到数据,这个不是指针,是一个数组
wudianjun2001 发表于 2018-8-9 17:04
读时间的话定时读就可以了,不行的话先网上找个IO口模拟IIC的程序先试试,我一般都喜欢用模拟的,不喜欢MCU ...
怎么才能定时读取啊?我是初学的
hhhhhhhaa 发表于 2018-8-10 10:52
怎么才能定时读取啊?我是初学的
定时中断啊
wudianjun2001 发表于 2018-8-10 11:49
定时中断啊
不会用定时中断
定时中断读取也不对啊。应该是像上面说的用delay的方式,可以用系统默认的systick做。
安 发表于 2018-8-10 13:43
定时中断读取也不对啊。应该是像上面说的用delay的方式,可以用系统默认的systick做。 ...
有sys的示例吗
官方例程库里面全有。
安 发表于 2018-8-10 16:31
官方例程库里面全有。
太复杂了,看不懂,自己写了个延时程序 ,调用一下就好了
void Delay_MS(u16 dly)
{
u16 i,j;
for(i=0;i<dly;i++)
for(j=10000;j>0;j--);
}
IIC.h文件
#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"
#include "delay.h"
//IIC所有操作函数
void IIC_Init(void) ; //初始化IIC的IO口
u8 IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(void); //IIC读取一个字节
#endif
经过几个月的学习,最近又想好好去研究一下PCF8563与IIC通讯,重新编写了IIC.c 和IIC.h的文件,最基本的文件编写完成后,开始编写PCF8563.c 和pcf8563.h文件 最后在主函数里直接调用 具体代码如下
#include "myiic.h"
#define SCL_PIN GPIO_Pin_6
#define SDA_PIN GPIO_Pin_7
#define SCL_H GPIOB->BSRR = SCL_PIN
#define SCL_L GPIOB->BRR= SCL_PIN
#define SDA_H GPIOB->BSRR = SDA_PIN
#define SDA_L GPIOB->BRR= SDA_PIN
#define SCL_read GPIOB->IDR& SCL_PIN
#define SDA_read GPIOB->IDR& SDA_PIN
#defineFALSE(0)
#defineTRUE (1)
#define I2C_delay() delay_ms(4)
//第一步初始化IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//产生IIC起始信号
u8 IIC_Start(void)
{
SDA_H;
delay_ms(10);
SCL_H;
delay_ms(10);
// if(!SDA_read)return FALSE; //SDA线为低电平则总线忙,退出
SDA_L;
delay_ms(10);
// if(SDA_read)return FALSE; //SDA线为高电平则总线出错,退出
SCL_L;
delay_ms(10);
return TRUE;
}
//产生IIC停止信号
void IIC_Stop(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SDA_H;
I2C_delay();
SCL_L;
I2C_delay();
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
SCL_L;
return FALSE;
}
SCL_L;
return TRUE;
}
//产生ACK应答
void IIC_Ack(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
//不产生ACK应答
void IIC_NAck(void)
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
u8 i=8;
while(i--)
{
SCL_L;
I2C_delay();
if(txd&0x80)
SDA_H;
else
SDA_L;
txd<<=1;
I2C_delay();
SCL_H;
I2C_delay();
}
SCL_L;
// return IIC_Wait_Ack();
}
u8 IIC_Read_Byte(void)
{
u8 i=8;
u8 ReceiveByte=0;
SDA_H;
while(i--)
{
ReceiveByte<<=1;
SCL_L;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
ReceiveByte|=0x01;
}
}
SCL_L;
return ReceiveByte;
}
以上是iic.c和iic.h 文件其中iic 发送数据的时候可以把主机发送后的等待加进去 这样写pcf8563的时候方便些 ,
这一部分是pcf8563.h 的文件
#ifndef __PCF8563_H
#define __PCF8563_H
#include "sys.h"
#include "myiic.h"
#include "string.h"
typedef struct
{
unsigned charyear;
unsigned charmon;
unsigned charweek;
unsigned charday;
unsigned charhour;
unsigned charmin;
unsigned charsec;
}sTime;
extern sTime time;
void Get_Time(void);
void Set_Time(void);
#endif
下面是pcf8563.c 的文件
#include "pcf8563.h"
/*-----------------------------------------------------------------
函数名: ByteToPbcd
功能: 将二进制数转换成BCD码.
输入: 2进制数.
输出: 无.
返回: BCD码.
BIN码就是二进制编码。
比如十进制数的11,用BIN码表示就是1011;
左边的1表示十制的8,左边第三位的1表示十制的2,
左边第四位的1表示十制的1,
(即 8+2+1=11)
BCD码就是用四位二进制数表示一位十进制数的编码,
比如十进制数11用BCE码表示就是00010001;
前面的0001表示十进制的十位的1,
后面买的0001表示十进制的个位的1.
--------------------------------------------------------------------*/
u8 PCF8563_ByteToPbcd(u8_ucHex/* 二进制数 */)
{
return ((_ucHex / 10) << 4) + (_ucHex % 10);
}
/*------------------------------------------------------------------
* 函数名: PbcdToByte
* 功能: 将PBCD数据转换成HEX型数据.
* 输入: bPbcd 待转换的PBCD数据.
* 输出: 无.
* 返回: uint8_t 转换后的HEX数据.
BIN码就是二进制编码。
比如十进制数的11,用BIN码表示就是1011;
左边的1表示十制的8,左边第三位的1表示十制的2,
左边第四位的1表示十制的1,
(即 8+2+1=11)
BCD码就是用四位二进制数表示一位十进制数的编码,
比如十进制数11用BCE码表示就是00010001;
前面的0001表示十进制的十位的1,
后面买的0001表示十进制的个位的1.
---------------------------------------------------------------------*/
u8 PCF8563_PbcdToByte(u8 _ucPbcd /* 待转换的PBCD数据 */)
{
return ((10 * (_ucPbcd >> 4)) + (_ucPbcd & 0x0f));
}
/*******************************************************************************
* 文件名:void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
* 描述: PCF8563某寄存器写入一个字节数据
* 功能:REG_ADD:要操作寄存器地址 dat: 要写入的数据
* 作者:
* 版本号:
*******************************************************************************/
unsigned char PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
{
if(!IIC_Start())
{
return 0;
}
IIC_Send_Byte(0xA2);//读地址 A3 read A3H;写地址是A2write A2H
if (!IIC_Wait_Ack())
{
IIC_Stop();
return 0;
}
IIC_Send_Byte(REG_ADD);
IIC_Wait_Ack();
IIC_Send_Byte(dat);//发送数据
IIC_Wait_Ack();
IIC_Stop();
return 1;
}
/*******************************************************************************
* 文件名:unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
* 描述: PCF8563某寄存器读取一个字节数据
* 功能:REG_ADD:要操作寄存器地址 读取得到的寄存器的值
* 作者:
* 版本号:
*******************************************************************************/
unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
{
u8ReData;
IIC_Start();
IIC_Send_Byte(0xA2);//读地址 A3 read A3H;写地址是A2write A2H
if (!IIC_Wait_Ack())
{
IIC_Stop();
}
IIC_Send_Byte(REG_ADD);//确定要操作的寄存器
IIC_Wait_Ack();
IIC_Start();//重启总线
IIC_Send_Byte(0xA3);//发送读取命令
IIC_Wait_Ack();
ReData = IIC_Read_Byte();//读取数据
IIC_NAck();//发送非应答信号结束数据传送
IIC_Stop();
return ReData;
}
/*******************************************************************************
* 文件名:void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
* 描述: PCF8563写入多组数据
* 功能:REG_ADD:要操作寄存器起始地址 num: 写入数据数量 *WBuff: 写入数据缓存
* 作者:
* 版本号:
*******************************************************************************/
u8 PCF8563_Write_nByte(u8* pBuffer, u16 WriteAddr, u16 Num)
{
IIC_Start();
IIC_Send_Byte(0xA2);//读地址 A3 read A3H;写地址是A2write A2H
if (!IIC_Wait_Ack())
{
IIC_Stop();
return 0;
}
IIC_Send_Byte(WriteAddr);//定位起始寄存器地址
IIC_Wait_Ack();
while(Num--)
{
IIC_Send_Byte(* pBuffer);
IIC_Wait_Ack();
pBuffer++;
}
IIC_Stop();
return 1;
}
/*******************************************************************************
* 文件名:void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
* 描述: PCF8563读取多组数据
* 功能:REG_ADD:要操作寄存器起始地址 num: 读取数据数量 *RBuff: 读取数据缓存
* 作者:
* 版本号:
*******************************************************************************/
u8 PCF8563_Read_nByte(u8* pBuffer, u16 WriteAddr, u16 NumByteToRead)
{
if(!IIC_Start())
{
return 0;
}
IIC_Send_Byte(0xA2);//读地址 A3 read A3H;写地址是A2write A2H
if (!IIC_Wait_Ack())
{
IIC_Stop();
return 0;
}
IIC_Send_Byte(WriteAddr);//定位起始寄存器地址
if(!IIC_Wait_Ack())
{
IIC_Stop();
return 0;
}
IIC_Start();
IIC_Send_Byte(0xA3);
IIC_Wait_Ack();
while(NumByteToRead)
{
*pBuffer = IIC_Read_Byte();
if(NumByteToRead == 1)
{
IIC_NAck();
}
else
{
IIC_Ack();
pBuffer++;
}
NumByteToRead--;
}
IIC_Stop();
return 1;
}
/*******************************************************************************
* 文件名:void Set_Time(sTime* time)
* 描述: PCF8563设置时间信息
* 功能:时间初始化
* 作者:
* 版本号:
*******************************************************************************/
void Set_Time(void)
{
unsigned char ucBuf;
ucBuf = PCF8563_ByteToPbcd(time.sec); //将字节转换为BCD码
ucBuf = PCF8563_ByteToPbcd(time.min);
ucBuf = PCF8563_ByteToPbcd(time.hour);
ucBuf = PCF8563_ByteToPbcd(time.day);
ucBuf = PCF8563_ByteToPbcd(time.mon);
ucBuf = PCF8563_ByteToPbcd(time.year);/* 年低位 */
PCF8563_Write_nByte(ucBuf,0x02,7);
}
/*******************************************************************************
* 文件名:void Get_Time(sTime* time)
* 描述: PCF8563读取时间信息
* 功能:
* 作者:
* 版本号:
*******************************************************************************/
void Get_Time(void)
{
unsigned char ucaBuf;
PCF8563_Read_nByte(ucaBuf,0x02,7);
time.sec=ucaBuf & 0x7F;
time.min=ucaBuf & 0x7F;
time.hour =ucaBuf & 0x3F;
time.day=ucaBuf & 0x3F;
time.mon=ucaBuf & 0x1F;
time.year =ucaBuf;
// time.sec=PCF8563_PbcdToByte(ucaBuf & 0x7F);
// time.min=PCF8563_PbcdToByte(ucaBuf & 0x7F);
// time.hour =PCF8563_PbcdToByte(ucaBuf & 0x3F);
// time.day=PCF8563_PbcdToByte(ucaBuf & 0x3F);
// time.mon=PCF8563_PbcdToByte(ucaBuf & 0x1F);
// time.year =PCF8563_PbcdToByte(ucaBuf);
}
下面是主函数的调用
#include "HEAD.h"
sTime time;
int main(void)
{
u8 key;
time.year=18;
time.mon=12;
time.day=17;
time.hour=9;
time.min =55;
time.sec =15;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
uart_init(9600); //串口初始化为9600
IIC_Init(); //IIC初始化
Set_Time();
while(1)
{
Get_Time();
key=time.year;
key=time.mon;
key=time.day;
key=time.hour;
key=time.min;
key=time.sec;
RS232_Send_Data(key,6);
delay_ms(500);
}
}
为了显示方便 把pcf8563最后的读取部分做了修改,使得显示是BCD码格式的,然后通过串口助手的16进制读取 显示的时间就是具体的时间了