标题:
STC51单片机IIC例程
[打印本页]
作者:
hanbinghyj0215
时间:
2017-9-18 16:44
标题:
STC51单片机IIC例程
初学51单片机,请多关照
代码下载:
51 IIC示例.zip
(65.27 KB, 下载次数: 62)
2017-9-18 16:44 上传
点击文件名下载附件
下载积分: 黑币 -5
/******************** (C) COPYRIGHT 2015 ********************
* 文件名 : main.c
* 作者 : 优灵电子开发团队
* 版本 : V3.1.0.0
* 日期 : 2015-5-10
* 描述 : 接收来自串口的简单数据,给模块用IIC发送对应命令,执行成功后
直接通过串口返回数据。
* 技术支持 : QQ: 3419865840
********************************************************************************/
/* 包含文件 -------------------------------------------------------------------*/
#include"main.h"
#include<intrins.h>
/* 类型定义 -------------------------------------------------------------------*/
typedef struct _CMD
{
unsigned char Buffer[32];
unsigned char Point;
unsigned char RecFlag;
}CMD;
/* 宏定义 ---------------------------------------------------------------------*/
#define SlaveAddress 0X00
/* 本文件使用的变量 -----------------------------------------------------------*/
sbit SCL = P1^7;
sbit SDA = P1^6;
CMD Cmd;
/* 本文件使用的函数声明 -------------------------------------------------------*/
void Delay5us();
void IIC_Start();
void IIC_Stop();
void IIC_SendByte(unsigned char dat);
unsigned char IIC_RecvByte();
void IIC_SendACK(bit ack);
bit IIC_RecvACK();
unsigned char CheckSum(unsigned char *dat, unsigned char num);
void ClearBuffer(void);
void Command(void);
/* 本文件函数体 ---------------------------------------------------------------*/
/*******************************************************************************
* 函数名 : main
* 描述 : 主函数
* 输入 : 无
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void main(void)
{
//串口初始化,单片机型号STC89C52RC,晶振是11.0592M,波特率9600
SCON = 0X50;
TMOD = 0X20;
TH1 = TL1 = 0XFD;
TR1 = 1;
while(1)
{
if(RI)
{
RI = 0;
//一键读卡命令
if(SBUF == 0x10)
{
Cmd.Buffer[0] = 0x03; //命令长度
Cmd.Buffer[1] = 0x00; //地址
Cmd.Buffer[2] = 0x10; //命令字
Command();
//正确时返回10字节
//0.命令长度 为0x0A
//1.命令字节为0x90
//2.执行状态为0
//3.4.卡类型
//5.6.7.8卡号
//错误时返回3字节
//0.命令长度为0x03
//1.命令字为0x90
//2.执行状态可能是0xfe,0xff
}
//读块数据
else if(SBUF == 0X11)
{
Cmd.Buffer[0] = 0x04; //命令长度
Cmd.Buffer[1] = 0x00; //地址
Cmd.Buffer[2] = 0x11; //命令字
Cmd.Buffer[3] = 0x01; //块号
Command();
}
//写块数据
else if(SBUF == 0X12)
{
Cmd.Buffer[0] = 0x14;//命令长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x12;//命令字
Cmd.Buffer[3] = 0x01;//块号
Cmd.Buffer[4] = 0x00;//数据
Cmd.Buffer[5] = 0x11;
Cmd.Buffer[6] = 0x22;
Cmd.Buffer[7] = 0x33;
Cmd.Buffer[8] = 0x44;
Cmd.Buffer[9] = 0x55;
Cmd.Buffer[10] = 0x66;
Cmd.Buffer[11] = 0x77;
Cmd.Buffer[12] = 0x88;
Cmd.Buffer[13] = 0x99;
Cmd.Buffer[14] = 0xAA;
Cmd.Buffer[15] = 0xBB;
Cmd.Buffer[16] = 0xCC;
Cmd.Buffer[17] = 0xDD;
Cmd.Buffer[18] = 0xEE;
Cmd.Buffer[19] = 0xFF;
Command();
}
//办卡
else if(SBUF == 0X13)
{
Cmd.Buffer[0] = 0x09;//命令长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x13;//命令字
Cmd.Buffer[3] = 0x01;//块号
Cmd.Buffer[4] = 0x00;//固定为0
Cmd.Buffer[5] = 0x00;//四字节数据
Cmd.Buffer[6] = 0x00;
Cmd.Buffer[7] = 0x00;
Cmd.Buffer[8] = 0x00;
Command();
}
//恢复卡
else if(SBUF == 0X14)
{
Cmd.Buffer[0] = 0x07;//命令长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x14;//命令字
Cmd.Buffer[3] = 0x01;//块号
Cmd.Buffer[4] = 0x38;//固定
Cmd.Buffer[5] = 0x52;//固定
Cmd.Buffer[6] = 0x7A;//固定
Command();
}
//充值
else if(SBUF == 0X15)
{
Cmd.Buffer[0] = 0x08;//长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x15;//命令字
Cmd.Buffer[3] = 0x01;//块号
Cmd.Buffer[4] = 0x00;//四字节数值
Cmd.Buffer[5] = 0x00;
Cmd.Buffer[6] = 0x00;
Cmd.Buffer[7] = 0x00;
Command();
}
//扣款
else if(SBUF == 0X16)
{
Cmd.Buffer[0] = 0x08;//长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x16;//命令字
Cmd.Buffer[3] = 0x01;//块号
Cmd.Buffer[4] = 0x00;//四字节数值
Cmd.Buffer[5] = 0x00;
Cmd.Buffer[6] = 0x00;
Cmd.Buffer[7] = 0x00;
Command();
}
//装载密码
else if(SBUF == 0X2B)
{
Cmd.Buffer[0] = 0x15;//长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x2B;//命令字
Cmd.Buffer[3] = 0xFF;//6字节密钥A
Cmd.Buffer[4] = 0xFF;
Cmd.Buffer[5] = 0xFF;
Cmd.Buffer[6] = 0xFF;
Cmd.Buffer[7] = 0xFF;
Cmd.Buffer[8] = 0xFF;
Cmd.Buffer[9] = 0xFF;//6字节密钥B
Cmd.Buffer[10] = 0xFF;
Cmd.Buffer[11] = 0xFF;
Cmd.Buffer[12] = 0xFF;
Cmd.Buffer[13] = 0xFF;
Cmd.Buffer[14] = 0xFF;
Cmd.Buffer[15] = 0x00;//密钥模式
Cmd.Buffer[16] = 0x03;//固定03
Cmd.Buffer[17] = 0x08;//固定08
Cmd.Buffer[18] = 0x05;//固定05
Cmd.Buffer[19] = 0x02;//固定02
Cmd.Buffer[20] = 0x07;//固定07
Command();
}
//设置波特率
else if(SBUF == 0X2C)
{
Cmd.Buffer[0] = 0x0A;//长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x2C;//命令字
Cmd.Buffer[3] = 0x00;//四字节波特率(19200)
Cmd.Buffer[4] = 0x00;
Cmd.Buffer[5] = 0x4B;
Cmd.Buffer[6] = 0x00;
Cmd.Buffer[7] = 0x98;//固定98
Cmd.Buffer[8] = 0x24;//固定24
Cmd.Buffer[9] = 0x31;//固定31
Command();
}
//设置地址
else if(SBUF == 0X2D)
{
Cmd.Buffer[0] = 0x07;//长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x2D;//命令字
Cmd.Buffer[3] = 0x01;//新地址
Cmd.Buffer[4] = 0x37;//固定37
Cmd.Buffer[5] = 0x21;//固定21
Cmd.Buffer[6] = 0x56;//固定56
Command();
}
//设置工作模式
else if(SBUF == 0X2E)
{
Cmd.Buffer[0] = 0x0D;//长度
Cmd.Buffer[1] = 0x00;//地址
Cmd.Buffer[2] = 0x2E;//命令字
Cmd.Buffer[3] = 0x00;//模式
Cmd.Buffer[4] = 0x0A;//模式+0A
Cmd.Buffer[5] = 0x01;//块号
Cmd.Buffer[6] = 0x00;//四字节操作值
Cmd.Buffer[7] = 0x00;
Cmd.Buffer[8] = 0x00;
Cmd.Buffer[9] = 0x01;
Cmd.Buffer[10] = 0x23;//固定23
Cmd.Buffer[11] = 0x12;//固定12
Cmd.Buffer[12] = 0x54;//固定54
Command();
}
}
}
}
/*******************************************************************************
* 函数名 : Command
* 描述 : 执行命令,发送IIC数据,接收IIC数据,串口发出
* 输入 : 无
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void Command(void)
{
unsigned char i;
//校验
Cmd.Buffer[Cmd.Buffer[0]] = CheckSum(Cmd.Buffer, Cmd.Buffer[0]);
//开始发送
IIC_Start();
IIC_SendByte(SlaveAddress);
for(i = 0; i < Cmd.Buffer[0] + 1; i++)
{
IIC_SendByte(Cmd.Buffer[i]);
}
IIC_Stop();
ClearBuffer();
//开始接收
IIC_Start();
IIC_SendByte(SlaveAddress|0x01);
do
{
//模块正忙时为返回7F
Cmd.Buffer[0] = IIC_RecvByte();
IIC_SendACK(0);
}while(Cmd.Buffer[0] == 0x7F);
for(i = 0; i < Cmd.Buffer[0]-1; i++)
{
Cmd.Buffer[i+1] = IIC_RecvByte();
IIC_SendACK(0);
}
Cmd.Buffer[i+1] = IIC_RecvByte();
IIC_SendACK(1);
IIC_Stop();
//开始从串口发送
for(i = 0; i < Cmd.Buffer[0] + 1; i++)
{
SBUF = Cmd.Buffer[i];TI = 0; while(TI == 0);
}
}
/*******************************************************************************
* 函数名 : ClearBuffer
* 描述 : 清除缓存
* 输入 : 无
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void ClearBuffer(void)
{
unsigned char i;
for(i = 0; i < 32; i++)
{
Cmd.Buffer[i] = 0;
}
}
/*******************************************************************************
* 函数名 : CheckSum
* 描述 : 校验函数
* 输入 : dat: 校验的数据数组
num: 校验的个数
* 输出 : 无
* 返回 : 校验码
*******************************************************************************/
unsigned char CheckSum(unsigned char *dat, unsigned char num)
{
unsigned char bTemp = 0, i;
for(i = 0; i < num; i ++){bTemp ^= dat[i];}
return bTemp;
}
/*******************************************************************************
* 函数名 : IIC_SendByte
* 描述 : IIC发送一字节数据
* 输入 : dat: 字节数据
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void IIC_SendByte(unsigned char dat)
{
unsigned char i;
for (i = 0; i < 8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
IIC_RecvACK();
}
/*******************************************************************************
* 函数名 : IIC_RecvByte
* 描述 : IIC接收一字节数据
* 输入 : 无
* 输出 : 无
* 返回 : 一字节数据
*******************************************************************************/
unsigned char IIC_RecvByte()
{
unsigned char i;
unsigned char dat = 0;
SDA = 1; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL = 1; //拉高时钟线
Delay5us(); //延时
dat |= SDA; //读数据
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
return dat;
}
/*******************************************************************************
* 函数名 : IIC_SendACK
* 描述 : IIC发送应答
* 输入 : ack: 应答位
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void IIC_SendACK(bit ack)
{
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
/*******************************************************************************
* 函数名 : IIC_RecvACK
* 描述 : IIC接收应答
* 输入 : 无
* 输出 : 无
* 返回 : 应答位
*******************************************************************************/
bit IIC_RecvACK()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
/*******************************************************************************
* 函数名 : IIC_Start
* 描述 : IIC起始信号
* 输入 : 无
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void IIC_Start()
{
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
/*******************************************************************************
* 函数名 : IIC_Stop
* 描述 : IIC停止信号
* 输入 : 无
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void IIC_Stop()
{
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 1; //产生上升沿
Delay5us(); //延时
}
/*******************************************************************************
* 函数名 : Delay5us
* 描述 : 延时5微秒(STC89C52RC@11.0592M)
不同的工作环境,需要调整此函数
当改用1T的MCU时,请调整此延时函数
* 输入 : 无
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
复制代码
作者:
LXJ50
时间:
2017-9-18 20:43
楼主厉害!谢谢分享,下载学习。
作者:
1334022368
时间:
2018-1-3 21:54
不错,学习了
作者:
qidiao007
时间:
2019-12-18 09:57
下载了 学习!!!
作者:
lozoho
时间:
2020-10-26 15:42
学习了,感谢楼主啦
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1