📄 i2cclockandtms320lf2407.c
字号:
I2C串行日历时钟与TMS320LF2407的接口及应用
源程序代码:
// 该程序实现对I2C总线日历时钟芯片PCF8583的读写操作
#include "register.h"
// 系统初始化子程序
void sysinit()
{
asm( " setc INTM "); // 关闭总中断
asm( " clrc SXM ") ; // 抑制符号扩展
asm( " clrc OVM ") ; // 累加器结果正常溢出
asm( " clrc CNF ") ; // B0被配置为数据空间
*SCSR1=0X81FE; // CLKIN=6M,CLKOUT=24M
*WDCR=0X0E8 ; // 不使能看门狗
*IMR=0X00; // 禁止所有中断
*IFR=0X0FFFF; // 清除所有的中断标志
WSGR=0x0FFFF; // 不使能所有的等待状态
}
// 输入输出口初始化子程序
void IOINIT()
{
*MCRB=*MCRB&0X0FFD7; // 配置IOPC3和IOPC5为一般的I/O口方式
*PCDATDIR=*PCDATDIR|0X02828; // 配置IOPC3和IOPC5为输出方式,且SCL=SDA=1
}
// 软件延时子程序
void delay()
{
int i;
for(i=0X07D;i--;) { i=i;}
}
// 启动I2C总线子程序
void START()
{
*PCDATDIR=*PCDATDIR|0X028; // SDA=SCL=1
delay( ); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR&0X0FFDF; // SDA=0
delay(); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR&0X0FFF7; // SCL=0
delay(); // 软件延时,以使时序匹配
}
// 发送字节子程序
void TRANSMIT(TRAN)
int TRAN;
{
int flag,sz; // 定义需要的局部变量
*PCDATDIR=*PCDATDIR&0X0FFF7; // SCL=0
delay(); // 软件延时,以使时序匹配
for(flag=0x0080;flag!=0x00;flag=flag/2) {
sz=TRAN&flag; // 屏蔽掉不需要的位
if(sz==0) *PCDATDIR=*PCDATDIR&0X0FFDF;// 如果相应的位为0,则SDA=0
else *PCDATDIR=*PCDATDIR|0X020;// 如果相应的位为1,则SDA=1
delay(); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR|0X08; // SCL=1
delay(); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR&0X0FFF7; // SCL=0
delay(); // 软件延时,以使时序匹配
}
}
// 从机(即PCF8583芯片)应答子程序。返回值为0时,代表操作成功;返回值为1时,代表操作失败
int SLAVE_ACK()
{
int sz,k=0; // 定义所需要的局部变量
*PCDATDIR=*PCDATDIR|0X0020; // SDA=1
delay(); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR&0X0DFFF; // 设置IOPC5(SDA)为输入
delay(); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR|0X08; // SCL=1
delay(); // 软件延时,以使时序匹配
sz=*PCDATDIR&0X0020; // 检测数据位
if(sz==0X0020) k=1; // 如果数据位为1,则证明失败,则令k=1
else k=0; // 如果数据位为0,则证明成功,则保持k=0不变
*PCDATDIR=*PCDATDIR|0X2000; // 设置IOPC5(SDA)为输出
*PCDATDIR=*PCDATDIR&0X0FFD7; // SCL=SDA=0
return(k);
}
// I2C停止子程序
void STOP()
{
*PCDATDIR=*PCDATDIR&0X0FFDF; // SDA=0
delay();
*PCDATDIR=*PCDATDIR|0X0008; // SCL=1
delay( ); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR|0X0020; // SDA=1
}
// 字节写子程序,即向I2C器件写1个字节的数据,入口为地址BYTE_ADDR和需要写入的字节
// 内容T_DATA。返回值为0时,代表操作成功;返回值为1时,代表操作失败
int BYTE_WR(BYTE_ADDR,T_DATA)
int BYTE_ADDR,T_DATA;
{
int k;
START(); // 启动I2C总线
TRANSMIT(0X0A0); // 送写控制字
k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) TRANSMIT(BYTE_ADDR); // 送出地址
if(k==0) k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) TRANSMIT(T_DATA); // 送出需要保存的数据
if(k==0) k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) STOP(); // 设置停止状态
return(k);
}
// 接收一个字节子程序,出口为接收到的数据R_DATA
int RECEIVE()
{
int R_DATA=0,sz,i;
*PCDATDIR=*PCDATDIR&0X0DFFF; // 设置IOPC5(SDA)为输入
*PCDATDIR=*PCDATDIR&0X0FFF7; // SCL=0
delay(); // 软件延时,以使时序匹配
for(i=0;i<8;i++) {
R_DATA=R_DATA<<1; // R_DATA左移一位
*PCDATDIR=*PCDATDIR|0X0008; // SCL=1
delay(); // 软件延时,以使时序匹配
sz=*PCDATDIR&0X0020; // 取得相应的数据位
if(sz==0) R_DATA=R_DATA&0XFFFE; // 如果数据位为0,则R_DATA最低位清0
else R_DATA=R_DATA|0x0001; // 如果数据位为1,则R_DATA最低位置1
*PCDATDIR=*PCDATDIR&0X0FFF7; // SCL=0
delay(); // 软件延时,以使时序匹配
}
*PCDATDIR=*PCDATDIR|0X2000; // 设置IOPC5(SDA)为输出
return(R_DATA); // 返回接收的字节
}
// 主机无应答信号子程序
void NO_ACK()
{
*PCDATDIR=*PCDATDIR|0X0008; // SCL=1
delay(); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR&0X0FFF7; // SCL=0
}
// 主机应答子程序
void MASTER_ACK()
{
*PCDATDIR=*PCDATDIR&0X0FFF7; // SCL=0
*PCDATDIR=*PCDATDIR&0X0FFDF; // SDA=0
*PCDATDIR=*PCDATDIR|0X0008; // SCL=1
delay(); // 软件延时,以使时序匹配
*PCDATDIR=*PCDATDIR&0X0FFF7; // SCL=0
}
// 字节读子程序,即从I2C器件读出1个字节的数据,入口为需要读出的地址BYTE_ADDR,出口
// 为读出的数据R_DATA,通过C语言的参数传递功能实现。返回值为0X0FFFF时,表示操作失败;
// 否则操作成功
int BYTE_RD(int BYTE_ADDR)
{
int k,R_DATA;
START(); // 启动I2C总线
TRANSMIT(0XA0); // 送出写控制字,以写入地址字节
k=SLAVE_ACK( ); // 从机(即PCF8583芯片)应答
if(k==0) TRANSMIT(BYTE_ADDR);// 送出需要读出数据的地址
k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) {
START( ); // 启动I2C总线
TRANSMIT(0XA1);
} // 送出读控制字
k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) {
R_DATA=RECEIVE(); // 接收PCF8583发出的数据
NO_ACK(); // 主机不作应答
STOP(); // 设置停止状态
}
if(k==0) return(R_DATA); // 返回一个读出的数据
else return(0X0FFFF); // 如果整个读过程有误,则返回0X0FFFF
}
// 连续写子程序,入口为需要写的起始地址ADDR,存储需要写入数据的数组的首地址ARRY,需要
// 写入的数据的个数N
int CON_WR(ADDR,ARRAY,N)
int ADDR,*ARRAY,N;
{
int k;
START(); // 启动I2C总线
TRANSMIT(0X0A0); // 送写控制字
k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) TRANSMIT(ADDR); // 送出要写数据的起始地址
if(k==0) k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) {
for(;N>0;N--,ARRAY++) {
TRANSMIT(*ARRAY); // 送出需要保存的数据,保存在数组ARRAY中
k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答,地址自动加1
if(k==1) break;
}
}
STOP(); // 设置停止状态
return(k);
}
// 连续读子程序,入口为需要读的起始地址ADDR,存储读出数据的数组首地址ARRY,需要读出的
// 数据的个数N
int CON_RD(ADDR,ARRAY,N)
int ADDR,*ARRAY,N;
{
int k,R_DATA;
START(); // 启动I2C总线
TRANSMIT(0XA0); // 送出写控制字,以写入地址字节
k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) TRANSMIT(ADDR); // 送出需要读出数据的地址
k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) {
START(); // 启动I2C总线
TRANSMIT(0XA1);
} // 送出读控制字
k=SLAVE_ACK(); // 从机(即PCF8583芯片)应答
if(k==0) {
for(;N>1;N--,ARRAY++) {
R_DATA=RECEIVE(); // 接收PCF8583发出的数据
*ARRAY=R_DATA; // 读出的数据存入数组
MASTER_ACK(); // 主机应答,地址自动加1
}
R_DATA=RECEIVE(); // 接收PCF8583发出的数据
*ARRAY=R_DATA; // 读出的数据存入数组
NO_ACK(); // 主机不作应答
STOP(); // 设置停止状态
}
return(k); // k=0时表示操作成功,k=1时表示操作失败
}
// 主程序
main()
{
int k;
int R_DATA;
static int source[6]={0x0F,0x0E,0x0D,0x0C,0x0B,0x0A};
int result[6];
sysinit(); // 系统初始化
IOINIT(); // 输入输出口初始化
k=BYTE_WR(0x00,0x00); // 设置PCF8583的控制状态寄存器,其地址为0x00,值0x00代
// 表的意义请参考相关资料,若k==0,则证明写入成功;若k==1,
// 则证明写入失败
R_DATA=BYTE_RD(0x00); // 读出地址单元0X00的值,如果读出值为0X0FFFF,则表示读
// 出值有误
k=CON_WR(0x30,source,6); // 从0x30地址开始连续写入6个数据
k=CON_RD(0x30,result,6); // 把写入的数据连续读出
}
// 直接返回中断服务子程序
void interrupt nothing()
{
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -