找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4750|回复: 4
打印 上一主题 下一主题
收起左侧

STC51单片机IIC例程

[复制链接]
跳转到指定楼层
楼主
ID:233894 发表于 2017-9-18 16:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
初学51单片机,请多关照
代码下载:
51 IIC示例.zip (65.27 KB, 下载次数: 62)

  1. /******************** (C) COPYRIGHT 2015 ********************
  2. * 文件名          : main.c
  3. * 作者            : 优灵电子开发团队
  4. * 版本            : V3.1.0.0
  5. * 日期            : 2015-5-10
  6. * 描述            : 接收来自串口的简单数据,给模块用IIC发送对应命令,执行成功后
  7.                                                                                 直接通过串口返回数据。
  8. * 技术支持        : QQ: 3419865840
  9. ********************************************************************************/

  10. /* 包含文件 -------------------------------------------------------------------*/
  11. #include"main.h"
  12. #include<intrins.h>
  13. /* 类型定义 -------------------------------------------------------------------*/
  14. typedef struct _CMD
  15. {
  16.   unsigned char Buffer[32];
  17.   unsigned char Point;
  18.   unsigned char RecFlag;
  19. }CMD;
  20. /* 宏定义 ---------------------------------------------------------------------*/
  21. #define SlaveAddress 0X00
  22. /* 本文件使用的变量 -----------------------------------------------------------*/
  23. sbit SCL = P1^7;
  24. sbit SDA = P1^6;
  25. CMD Cmd;
  26. /* 本文件使用的函数声明 -------------------------------------------------------*/
  27. void Delay5us();
  28. void IIC_Start();
  29. void IIC_Stop();
  30. void IIC_SendByte(unsigned char dat);
  31. unsigned char IIC_RecvByte();
  32. void IIC_SendACK(bit ack);
  33. bit IIC_RecvACK();
  34. unsigned char CheckSum(unsigned char *dat, unsigned char num);
  35. void ClearBuffer(void);
  36. void Command(void);
  37. /* 本文件函数体 ---------------------------------------------------------------*/

  38. /*******************************************************************************
  39. * 函数名         : main
  40. * 描述           : 主函数
  41. * 输入           : 无
  42. * 输出           : 无
  43. * 返回           : 无
  44. *******************************************************************************/
  45. void main(void)
  46. {
  47.         //串口初始化,单片机型号STC89C52RC,晶振是11.0592M,波特率9600
  48.         SCON = 0X50;
  49.         TMOD = 0X20;
  50.         TH1 = TL1 = 0XFD;
  51.         TR1 = 1;
  52.        
  53.         while(1)
  54.         {
  55.                 if(RI)
  56.                 {
  57.                         RI = 0;
  58.                         //一键读卡命令
  59.                         if(SBUF  == 0x10)
  60.                         {
  61.                                 Cmd.Buffer[0] = 0x03;        //命令长度
  62.                                 Cmd.Buffer[1] = 0x00;        //地址
  63.                                 Cmd.Buffer[2] = 0x10; //命令字
  64.                                
  65.                                 Command();
  66.                                 //正确时返回10字节
  67.                                 //0.命令长度 为0x0A
  68.                                 //1.命令字节为0x90
  69.                                 //2.执行状态为0
  70.                                 //3.4.卡类型
  71.                                 //5.6.7.8卡号
  72.                                 //错误时返回3字节
  73.                                 //0.命令长度为0x03
  74.                                 //1.命令字为0x90
  75.                                 //2.执行状态可能是0xfe,0xff
  76.                         }
  77.                         //读块数据
  78.                         else if(SBUF == 0X11)
  79.                         {
  80.                                 Cmd.Buffer[0] = 0x04;        //命令长度
  81.                                 Cmd.Buffer[1] = 0x00; //地址
  82.                                 Cmd.Buffer[2] = 0x11; //命令字
  83.                                 Cmd.Buffer[3] = 0x01; //块号
  84.                                
  85.                                 Command();
  86.                         }
  87.                         //写块数据
  88.                         else if(SBUF == 0X12)
  89.                         {
  90.                                 Cmd.Buffer[0] = 0x14;//命令长度
  91.                                 Cmd.Buffer[1] = 0x00;//地址
  92.                                 Cmd.Buffer[2] = 0x12;//命令字
  93.                                 Cmd.Buffer[3] = 0x01;//块号
  94.                                 Cmd.Buffer[4] = 0x00;//数据
  95.                                 Cmd.Buffer[5] = 0x11;
  96.                                 Cmd.Buffer[6] = 0x22;
  97.                                 Cmd.Buffer[7] = 0x33;
  98.                                 Cmd.Buffer[8] = 0x44;
  99.                                 Cmd.Buffer[9] = 0x55;
  100.                                 Cmd.Buffer[10] = 0x66;
  101.                                 Cmd.Buffer[11] = 0x77;
  102.                                 Cmd.Buffer[12] = 0x88;
  103.                                 Cmd.Buffer[13] = 0x99;
  104.                                 Cmd.Buffer[14] = 0xAA;
  105.                                 Cmd.Buffer[15] = 0xBB;
  106.                                 Cmd.Buffer[16] = 0xCC;
  107.                                 Cmd.Buffer[17] = 0xDD;
  108.                                 Cmd.Buffer[18] = 0xEE;
  109.                                 Cmd.Buffer[19] = 0xFF;
  110.                                
  111.                                 Command();
  112.                         }
  113.                         //办卡
  114.                         else if(SBUF == 0X13)
  115.                         {
  116.                                 Cmd.Buffer[0] = 0x09;//命令长度
  117.                                 Cmd.Buffer[1] = 0x00;//地址
  118.                                 Cmd.Buffer[2] = 0x13;//命令字
  119.                                 Cmd.Buffer[3] = 0x01;//块号
  120.                                 Cmd.Buffer[4] = 0x00;//固定为0
  121.                                 Cmd.Buffer[5] = 0x00;//四字节数据
  122.                                 Cmd.Buffer[6] = 0x00;
  123.                                 Cmd.Buffer[7] = 0x00;
  124.                                 Cmd.Buffer[8] = 0x00;
  125.                                
  126.                                 Command();
  127.                         }
  128.                         //恢复卡
  129.                         else if(SBUF == 0X14)
  130.                         {
  131.                                 Cmd.Buffer[0] = 0x07;//命令长度
  132.                                 Cmd.Buffer[1] = 0x00;//地址
  133.                                 Cmd.Buffer[2] = 0x14;//命令字
  134.                                 Cmd.Buffer[3] = 0x01;//块号
  135.                                 Cmd.Buffer[4] = 0x38;//固定
  136.                                 Cmd.Buffer[5] = 0x52;//固定
  137.                                 Cmd.Buffer[6] = 0x7A;//固定
  138.                                
  139.                                 Command();
  140.                         }
  141.                         //充值
  142.                         else if(SBUF == 0X15)
  143.                         {
  144.                                 Cmd.Buffer[0] = 0x08;//长度
  145.                                 Cmd.Buffer[1] = 0x00;//地址
  146.                                 Cmd.Buffer[2] = 0x15;//命令字
  147.                                 Cmd.Buffer[3] = 0x01;//块号
  148.                                 Cmd.Buffer[4] = 0x00;//四字节数值
  149.                                 Cmd.Buffer[5] = 0x00;
  150.                                 Cmd.Buffer[6] = 0x00;
  151.                                 Cmd.Buffer[7] = 0x00;

  152.                                 Command();
  153.                         }
  154.                         //扣款
  155.                         else if(SBUF == 0X16)
  156.                         {
  157.                                 Cmd.Buffer[0] = 0x08;//长度
  158.                                 Cmd.Buffer[1] = 0x00;//地址
  159.                                 Cmd.Buffer[2] = 0x16;//命令字
  160.                                 Cmd.Buffer[3] = 0x01;//块号
  161.                                 Cmd.Buffer[4] = 0x00;//四字节数值
  162.                                 Cmd.Buffer[5] = 0x00;
  163.                                 Cmd.Buffer[6] = 0x00;
  164.                                 Cmd.Buffer[7] = 0x00;
  165.                                
  166.                                 Command();
  167.                         }
  168.                         //装载密码
  169.                         else if(SBUF == 0X2B)
  170.                         {
  171.                                 Cmd.Buffer[0] = 0x15;//长度
  172.                                 Cmd.Buffer[1] = 0x00;//地址
  173.                                 Cmd.Buffer[2] = 0x2B;//命令字
  174.                                 Cmd.Buffer[3] = 0xFF;//6字节密钥A
  175.                                 Cmd.Buffer[4] = 0xFF;
  176.                                 Cmd.Buffer[5] = 0xFF;
  177.                                 Cmd.Buffer[6] = 0xFF;
  178.                                 Cmd.Buffer[7] = 0xFF;
  179.                                 Cmd.Buffer[8] = 0xFF;
  180.                                 Cmd.Buffer[9] = 0xFF;//6字节密钥B
  181.                                 Cmd.Buffer[10] = 0xFF;
  182.                                 Cmd.Buffer[11] = 0xFF;
  183.                                 Cmd.Buffer[12] = 0xFF;
  184.                                 Cmd.Buffer[13] = 0xFF;
  185.                                 Cmd.Buffer[14] = 0xFF;
  186.                                 Cmd.Buffer[15] = 0x00;//密钥模式
  187.                                 Cmd.Buffer[16] = 0x03;//固定03
  188.                                 Cmd.Buffer[17] = 0x08;//固定08
  189.                                 Cmd.Buffer[18] = 0x05;//固定05
  190.                                 Cmd.Buffer[19] = 0x02;//固定02
  191.                                 Cmd.Buffer[20] = 0x07;//固定07
  192.                                
  193.                                 Command();
  194.                         }
  195.                         //设置波特率
  196.                         else if(SBUF == 0X2C)
  197.                         {
  198.                                 Cmd.Buffer[0] = 0x0A;//长度
  199.                                 Cmd.Buffer[1] = 0x00;//地址
  200.                                 Cmd.Buffer[2] = 0x2C;//命令字
  201.                                 Cmd.Buffer[3] = 0x00;//四字节波特率(19200)
  202.                                 Cmd.Buffer[4] = 0x00;
  203.                                 Cmd.Buffer[5] = 0x4B;
  204.                                 Cmd.Buffer[6] = 0x00;
  205.                                 Cmd.Buffer[7] = 0x98;//固定98
  206.                                 Cmd.Buffer[8] = 0x24;//固定24
  207.                                 Cmd.Buffer[9] = 0x31;//固定31
  208.                                
  209.                                 Command();
  210.                         }
  211.                         //设置地址
  212.                         else if(SBUF == 0X2D)
  213.                         {
  214.                                 Cmd.Buffer[0] = 0x07;//长度
  215.                                 Cmd.Buffer[1] = 0x00;//地址
  216.                                 Cmd.Buffer[2] = 0x2D;//命令字
  217.                                 Cmd.Buffer[3] = 0x01;//新地址
  218.                                 Cmd.Buffer[4] = 0x37;//固定37
  219.                                 Cmd.Buffer[5] = 0x21;//固定21
  220.                                 Cmd.Buffer[6] = 0x56;//固定56
  221.                                
  222.                                 Command();
  223.                         }
  224.                         //设置工作模式
  225.                         else if(SBUF == 0X2E)
  226.                         {
  227.                                 Cmd.Buffer[0] = 0x0D;//长度
  228.                                 Cmd.Buffer[1] = 0x00;//地址
  229.                                 Cmd.Buffer[2] = 0x2E;//命令字
  230.                                 Cmd.Buffer[3] = 0x00;//模式
  231.                                 Cmd.Buffer[4] = 0x0A;//模式+0A
  232.                                 Cmd.Buffer[5] = 0x01;//块号
  233.                                 Cmd.Buffer[6] = 0x00;//四字节操作值
  234.                                 Cmd.Buffer[7] = 0x00;
  235.                                 Cmd.Buffer[8] = 0x00;
  236.                                 Cmd.Buffer[9] = 0x01;
  237.                                 Cmd.Buffer[10] = 0x23;//固定23
  238.                                 Cmd.Buffer[11] = 0x12;//固定12
  239.                                 Cmd.Buffer[12] = 0x54;//固定54
  240.                                
  241.                                 Command();
  242.                         }
  243.                 }
  244.         }
  245. }

  246. /*******************************************************************************
  247. * 函数名         : Command
  248. * 描述           : 执行命令,发送IIC数据,接收IIC数据,串口发出
  249. * 输入           : 无
  250. * 输出           : 无
  251. * 返回           : 无
  252. *******************************************************************************/
  253. void Command(void)
  254. {
  255.         unsigned char i;
  256.        
  257.         //校验
  258.         Cmd.Buffer[Cmd.Buffer[0]] = CheckSum(Cmd.Buffer, Cmd.Buffer[0]);
  259.         //开始发送
  260.         IIC_Start();
  261.         IIC_SendByte(SlaveAddress);
  262.        
  263.         for(i = 0; i < Cmd.Buffer[0] + 1; i++)
  264.         {
  265.                 IIC_SendByte(Cmd.Buffer[i]);
  266.         }
  267.         IIC_Stop();
  268.        
  269.         ClearBuffer();
  270.        
  271.         //开始接收
  272.         IIC_Start();
  273.         IIC_SendByte(SlaveAddress|0x01);
  274.        
  275.         do
  276.         {
  277.                 //模块正忙时为返回7F
  278.                 Cmd.Buffer[0] = IIC_RecvByte();
  279.                 IIC_SendACK(0);
  280.         }while(Cmd.Buffer[0] == 0x7F);
  281.        
  282.         for(i = 0; i < Cmd.Buffer[0]-1; i++)
  283.         {
  284.                 Cmd.Buffer[i+1] = IIC_RecvByte();
  285.                 IIC_SendACK(0);
  286.         }
  287.         Cmd.Buffer[i+1] = IIC_RecvByte();
  288.         IIC_SendACK(1);
  289.        
  290.         IIC_Stop();
  291.         //开始从串口发送
  292.         for(i = 0; i < Cmd.Buffer[0] + 1; i++)
  293.         {
  294.                 SBUF = Cmd.Buffer[i];TI = 0; while(TI == 0);
  295.         }
  296. }

  297. /*******************************************************************************
  298. * 函数名         : ClearBuffer
  299. * 描述           : 清除缓存
  300. * 输入           : 无
  301. * 输出           : 无
  302. * 返回           : 无
  303. *******************************************************************************/
  304. void ClearBuffer(void)
  305. {
  306.         unsigned char i;
  307.         for(i = 0; i < 32; i++)
  308.         {
  309.                 Cmd.Buffer[i] = 0;
  310.         }
  311. }

  312. /*******************************************************************************
  313. * 函数名         : CheckSum
  314. * 描述           : 校验函数
  315. * 输入           : dat: 校验的数据数组
  316.                                                                          num: 校验的个数
  317. * 输出           : 无
  318. * 返回           : 校验码
  319. *******************************************************************************/
  320. unsigned char CheckSum(unsigned char *dat, unsigned char num)
  321. {
  322.   unsigned char bTemp = 0, i;
  323.   
  324.   for(i = 0; i < num; i ++){bTemp ^= dat[i];}
  325.   return bTemp;
  326. }

  327. /*******************************************************************************
  328. * 函数名         : IIC_SendByte
  329. * 描述           : IIC发送一字节数据
  330. * 输入           : dat: 字节数据
  331. * 输出           : 无
  332. * 返回           : 无
  333. *******************************************************************************/
  334. void IIC_SendByte(unsigned char dat)
  335. {
  336.     unsigned char i;
  337.        
  338.     for (i = 0; i < 8; i++)     //8位计数器
  339.     {
  340.         dat <<= 1;              //移出数据的最高位
  341.         SDA = CY;               //送数据口
  342.         SCL = 1;                //拉高时钟线
  343.         Delay5us();             //延时
  344.         SCL = 0;                //拉低时钟线
  345.         Delay5us();             //延时
  346.     }
  347.     IIC_RecvACK();
  348. }

  349. /*******************************************************************************
  350. * 函数名         : IIC_RecvByte
  351. * 描述           : IIC接收一字节数据
  352. * 输入           : 无
  353. * 输出           : 无
  354. * 返回           : 一字节数据
  355. *******************************************************************************/
  356. unsigned char IIC_RecvByte()
  357. {
  358.     unsigned char i;
  359.     unsigned char dat = 0;
  360.     SDA = 1;                    //使能内部上拉,准备读取数据,
  361.     for (i=0; i<8; i++)         //8位计数器
  362.     {
  363.         dat <<= 1;
  364.         SCL = 1;                //拉高时钟线
  365.         Delay5us();             //延时
  366.         dat |= SDA;             //读数据               
  367.         SCL = 0;                //拉低时钟线
  368.         Delay5us();             //延时
  369.     }
  370.                
  371.     return dat;
  372. }

  373. /*******************************************************************************
  374. * 函数名         : IIC_SendACK
  375. * 描述           : IIC发送应答
  376. * 输入           : ack: 应答位
  377. * 输出           : 无
  378. * 返回           : 无
  379. *******************************************************************************/
  380. void IIC_SendACK(bit ack)
  381. {
  382.     SDA = ack;                  //写应答信号
  383.     SCL = 1;                    //拉高时钟线
  384.     Delay5us();                 //延时
  385.     SCL = 0;                    //拉低时钟线
  386.     Delay5us();                 //延时
  387. }

  388. /*******************************************************************************
  389. * 函数名         : IIC_RecvACK
  390. * 描述           : IIC接收应答
  391. * 输入           : 无
  392. * 输出           : 无
  393. * 返回           : 应答位
  394. *******************************************************************************/
  395. bit IIC_RecvACK()
  396. {
  397.     SCL = 1;                    //拉高时钟线
  398.     Delay5us();                 //延时
  399.     CY = SDA;                   //读应答信号
  400.     SCL = 0;                    //拉低时钟线
  401.     Delay5us();                 //延时
  402.     return CY;
  403. }

  404. /*******************************************************************************
  405. * 函数名         : IIC_Start
  406. * 描述           : IIC起始信号
  407. * 输入           : 无
  408. * 输出           : 无
  409. * 返回           : 无
  410. *******************************************************************************/
  411. void IIC_Start()
  412. {
  413.     SDA = 1;                    //拉高数据线
  414.     SCL = 1;                    //拉高时钟线
  415.     Delay5us();                 //延时
  416.     SDA = 0;                    //产生下降沿
  417.     Delay5us();                 //延时
  418.     SCL = 0;                    //拉低时钟线
  419. }

  420. /*******************************************************************************
  421. * 函数名         : IIC_Stop
  422. * 描述           : IIC停止信号
  423. * 输入           : 无
  424. * 输出           : 无
  425. * 返回           : 无
  426. *******************************************************************************/
  427. void IIC_Stop()
  428. {
  429.     SDA = 0;                    //拉低数据线
  430.     SCL = 1;                    //拉高时钟线
  431.     Delay5us();                 //延时
  432.     SDA = 1;                    //产生上升沿
  433.     Delay5us();                 //延时
  434. }

  435. /*******************************************************************************
  436. * 函数名         : Delay5us
  437. * 描述           : 延时5微秒(STC89C52RC@11.0592M)
  438.                                                                                 不同的工作环境,需要调整此函数
  439.                                                                                 当改用1T的MCU时,请调整此延时函数
  440. * 输入           : 无
  441. * 输出           : 无
  442. * 返回           : 无
  443. *******************************************************************************/
  444. void Delay5us()
  445. {
  446.         _nop_();_nop_();_nop_();_nop_();
  447.         _nop_();_nop_();_nop_();_nop_();
  448.         _nop_();_nop_();_nop_();_nop_();
  449.         _nop_();_nop_();_nop_();_nop_();
  450.         _nop_();_nop_();_nop_();_nop_();
  451.         _nop_();_nop_();_nop_();_nop_();
  452. }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:164988 发表于 2017-9-18 20:43 | 只看该作者
楼主厉害!谢谢分享,下载学习。
回复

使用道具 举报

板凳
ID:271078 发表于 2018-1-3 21:54 | 只看该作者
不错,学习了
回复

使用道具 举报

地板
ID:258676 发表于 2019-12-18 09:57 | 只看该作者
下载了 学习!!!
回复

使用道具 举报

5#
ID:317362 发表于 2020-10-26 15:42 | 只看该作者
学习了,感谢楼主啦
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表