滚印车间
您当前的位置:贴片加工 > 基础知识

关于51单片机SMBus总线的开启问题,细节问题

时间:2021-07-04 08:14:55  来源:  浏览量:
看了一个淘宝掏出来的基于51单片机的红外测温模块MLX90614的代码,因为理解的慢,上单片机课也睡着了
所以看了两三天,看到主函数的时候就觉得有个地方,难道不是没有必要的吗?想请各位前辈教导下,奔放的鞭策小妹

  1. #include
  2. #include
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. #define Nack_number 10
  6. //**************端口定义**************************************************
  7. uchar flag;            //LCD控制线接口
  8. sbit RS=P0^6;             //RS 端
  9. sbit RW=P0^7;          // 读写端
  10. sbit LCDE=P3^5;        //使能端
  11.            //mlx90614 端口定义
  12. sbit SCK=P3^7;        // 时钟线
  13. sbit SDA=P3^6;         // 数据线


  14. sbit DPY1 = P3^2;                      //温度显示第 1 个数码管段选
  15. sbit DPY2 = P3^3;                      //温度显示第 2 个数码管段选
  16. sbit DPY3 = P3^4;                      //温度显示第 3 个数码管段选
  17.   
  18. sbit row1 = P0^3;                           //矩阵键盘第 1 列
  19. sbit row2 = P0^4;                           //矩阵键盘第 2 列
  20. sbit row3 = P0^5;                           //矩阵键盘第 3 列
  21. sbit cow1 = P0^0;                           //矩阵键盘第 1 行  
  22. sbit cow2 = P0^1;                           //矩阵键盘第 2 行
  23. sbit cow3 = P0^2;                           //矩阵键盘第 3 行
  24. //************数据定义****************************************************
  25. bdata uchar flag1;       //可位寻址数据
  26. sbit bit_out=flag1^7;
  27. sbit bit_in=flag1^0;
  28. uchar tempH,tempL,err;

  29. void CALTEMP(uint TEMP);
  30. void ReadKey(void);
  31. void initint();
  32. void delay1(uint z);
  33. void show();
  34. uchar key_num;
  35. uchar mah[5];

  36. /********数码管码值定义*******************************************************/
  37. uchar code LED01[]={           //LED显示代码,0-9 共阳  不带小数点的   
  38. 0xC0,0xF9,0xA4,0xB0,
  39. 0x99,0x92,0x82,0xF8,
  40. 0x80,0x90};

  41. uchar code LED02[]={           //LED显示代码,0-9 共阳  带小数点的   
  42. 0x40,0x79,0x24,0x30,
  43. 0x19,0x12,0x02,0x78,
  44. 0x00,0x10};
  45. /**********全局变量定义******************************************************/
  46. bit b20ms,b100ms;   //定时标志位
  47. uchar c20ms,c100ms;     //定时毫秒数

  48. //**************************  LCD1602  ***********************************
  49. //向 LCD 写入命令或数据*****************************************************
  50. #define LCD_COMMAND   0         //命令
  51. #define LCD_DATA   1         // 数据
  52. #define LCD_CLEAR_SCREEN 0x01        // 清屏
  53. #define LCD_HOMING    0x02        // 光标返回原点
  54. //设置显示模式******* 0x08+   *********************************************
  55. #define LCD_SHOW   0x04      //显示开
  56. #define LCD_HIDE   0x00      //显示关
  57. #define LCD_CURSOR   0x02    //显示光标
  58. #define LCD_NO_CURSOR  0x00      //无光标
  59. #define LCD_FLASH   0x01      //光标闪动
  60. #define LCD_NO_FLASH  0x00      //光标不闪动
  61. //设置输入模式********** 0x04+ ********************************************
  62. #define LCD_AC_UP   0x02       //光标右移 AC+
  63. #define LCD_AC_DOWN   0x00        //默认 光标左移 AC-
  64. #define LCD_MOVE   0x01        //画面可平移
  65. #define LCD_NO_MOVE   0x00        //默认 画面不移动

  66. //**************************  mlx90614  ***********************************
  67. //command mode  命令模式
  68. #define RamAccess 0x00     // 对 RAM 操作
  69. #define EepomAccess 0x20     // 对 EEPRAM 操作
  70. #define Mode  0x60     //进入命令模式
  71. #define ExitMode 0x61     //退出命令模式
  72. #define ReadFlag 0xf0     //读标志
  73. #define EnterSleep 0xff     //进入睡眠模式
  74. //ram address read only RAM 地址(只读)
  75. #define AbmientTempAddr  0x03   //周围温度
  76. #define IR1Addr    0x04
  77. #define IR2Addr    0x05
  78. #define LineAbmientTempAddr 0x06     //环境温度
  79. /*0x0000 0x4074  16500  0.01/单元
  80.      -40    125*/
  81. #define LineObj1TempAddr 0x07   //目标温度,红外温度
  82. /*0x27ad-0x7fff  0x3559 22610 0.02/单元
  83.   -70.01-382.19  0.01   452.2*/
  84. #define LineObj2TempAddr 0x08
  85. //eepom address  EEPROM 地址
  86. #define TObjMaxAddr  0x00    //测量范围上限设定
  87. #define TObjMinAddr  0x01    //测量范围下限设定
  88. #define PWMCtrlAddr  0x02    //PWM 设定
  89. #define TaRangeAddr  0x03    //环境温度设定
  90. #define KeAddr   0x04    //频率修正系数
  91. #define ConfigAddr  0x05    //配置寄存器
  92. #define SMbusAddr  0x0e    //器件地址设定
  93. #define Reserverd1Addr 0x0f    //保留
  94. #define Reserverd2Addr 0x19    // 保留
  95. #define ID1Addr   0x1c    //ID 地址 1
  96. #define ID2Addr   0x1d    //ID 地址 2
  97. #define ID3Addr   0x1e    //ID 地址 3
  98. #define ID4Addr   0x1f    //ID 地址 4

  99. //************函数声明*****************************************************
  100. void start();         //MLX90614 发起始位子程序
  101. void stop();         //MLX90614 发结束位子程序
  102. uchar ReadByte(void);       //MLX90614接收字节子程序
  103. void send_bit(void);       //MLX90614 发送位子程序
  104. void SendByte(uchar number);     //MLX90614 接收字节子程序
  105. void read_bit(void);       //MLX90614 接收位子程序
  106. void delay(uint N);       //延时程序
  107. uint readtemp(void);       //读温度数据
  108. void init1602(void);       //LCD 初始化子程序
  109. void busy(void);        //LCD 判断忙子程序
  110. void cmd_wrt(uchar cmd);      //LCD 写命令子程序
  111. void dat_wrt(uchar dat);      //LCD 写数据子程序
  112. void display(uint Tem);      //显示子程序
  113. void Print(uchar *str);      //字符串显示程序

  114. //*************主函数*******************************************
  115. void main()
  116. {
  117. uint Tem;        //温度变量
  118.     initInt();
  119. SCK=1;
  120. SDA=1;
  121. delay(4);
  122. SCK=0;
  123. delay(1000);
  124. SCK=1;
  125. init1602();        // 初始化 LCD
  126. while(1)
  127. {
  128.         while(b100ms)    //每 100ms 扫描一次键盘
  129.         {
  130.          b100ms=0;
  131.       ReadKey();
  132.         }  

  133.         if(key_num==1)              //按下 1 键时,进行数码管显示
  134.         {
  135.          Tem=readtemp();
  136.          CALTEMP(Tem);
  137.          show();
  138.         }
  139.   
  140.         if(key_num!=1)      //液晶屏显示
  141.         {
  142.   Tem=readtemp();      //读取温度
  143.   cmd_wrt(0x01);      // 清屏
  144.   Print("  Temperature:    ");  //显示字符串  Temperature: 且换行
  145.   display(Tem);      //显示温度
  146.   Print(" ^C");     //显示摄氏度
  147.   delay(100000);      //延时再读取温度显示
  148.         }
  149. }
  150. }
  151. //------------------字符串显示程序--------------------------
  152. void Print(uchar *str)      //字符串显示程序
  153. {
  154. while(*str!='')      //直到字符串结束
  155. {
  156.   dat_wrt(*str);      // 转成 ASCII 码   
  157.   str++;        //指向下一个字符
  158. }
  159. }

  160. //--------------输入转换并显示(用于 LCD1602)--------------------
  161. void display(uint Tem)
  162. {
  163. uint T,a,b;
  164. T=Tem*2;
  165. if(T>=27315)       //温度为正
  166. {
  167.   T=T-27315;       //
  168.   a=T/100;       //温度整数
  169.   b=T-a*100;       //温度小数
  170.   if(a>=100)       //温度超过 100 度
  171.   {
  172.    dat_wrt(0x30+a/100);   //显示温度百位
  173.    dat_wrt(0x30+a%100/10);   //显示温度十位
  174.    dat_wrt(0x30+a%10);    //显示温度个位
  175.   }
  176.   else if(a>=10)      //温度超过 10 度
  177.   {
  178.    dat_wrt(0x30+a%100/10);   //显示温度十位
  179.    dat_wrt(0x30+a%10);    //显示温度个位
  180.   }
  181.   else        //温度不超过 10 度
  182.   {
  183.    dat_wrt(0x30+a);    //显示温度个位
  184.   }
  185.   dat_wrt(0x2e);      //显示小数点
  186.   if(b>=10)       //温度小数点后第 1 位数不等于 0
  187.   {
  188.   dat_wrt(0x30+b/10);     //显示温度小数点后第 1 位数
  189.   dat_wrt(0x30+b%10);     //显示温度小数点后第 2 位数
  190.   }
  191.   else        //温度小数点后第 1 位数等于 0
  192.   {
  193.    dat_wrt(0x30);     //显示温度小数点后第 1 位数 0
  194.    dat_wrt(0x30+b);    //显示温度小数点后第 2 位数
  195.   }
  196. }
  197. else         //温度为负
  198. {
  199.   T=27315-T;
  200.   a=T/100;
  201.   b=T-a*100;
  202.   dat_wrt(0x2d);      //显示负号
  203.   if(a>=10)       //温度低于负 10 度
  204.   {
  205.    dat_wrt(0x30+a/10);    //显示温度十位
  206.    dat_wrt(0x30+a%10);    //显示温度个位
  207.   }
  208.   else        //温度高于负 10 度
  209.   {
  210.    dat_wrt(0x30+a);    //显示温度个位
  211.   }
  212.   dat_wrt(0x2e);      //显示小数点
  213.   if(b>=10)       //温度小数点后第 1 位数不等于 0
  214.   {
  215.    dat_wrt(0x30+b/10);    //显示温度小数点后第 1 位数
  216.    dat_wrt(0x30+b%10);    //显示温度小数点后第 2 位数
  217.   }
  218.   else        //温度小数点后第 1 位数等于 0
  219.   {
  220.    dat_wrt(0x30);     //显示温度小数点后第 1 位数 0
  221.    dat_wrt(0x30+b);    //显示温度小数点后第 2 位数
  222.   }
  223. }
  224. }
  225. //--------------------根据十六进制计算温度------------------------------
  226. void CALTEMP(uint TEMP)
  227. {
  228.       uint T;
  229.       uint a,b;
  230.       uchar A4,A5,A6,A7,A8;
  231.       T=TEMP*2;
  232.       if(T>=27315)
  233.             {
  234.                T=T-27315;
  235.                a=T/100;
  236.                b=T-a*100;
  237.                if(a>=100)
  238.                    {
  239.                       A4=a/100;
  240.                       a=a%100;
  241.                       A5=a/10;
  242.                       a=a%10;
  243.                       A6=a;
  244.                     }
  245.                else if(a>=10)
  246.                     {
  247.                       A4=0;
  248.                       A5=a/10;
  249.                       a=a%10;
  250.                       A6=a;
  251.                     }
  252.                else  
  253.                     {
  254.                       A4=0;
  255.                       A5=0;
  256.                       A6=a;
  257.                     }
  258.                if(b>=10)
  259.                     {
  260.                       A7=b/10;
  261.                       b=b%10;
  262.                       A8=b;
  263.                     }
  264.                 else
  265.                     {
  266.                       A7=0;
  267.                       A8=b;
  268.                     }
  269.              }
  270.          else
  271.                {
  272.                   T=27315-T;
  273.                   a=T/100;
  274.                   b=T-a*100;
  275.                   A4=9;
  276.                   if(a>=10)
  277.                       {
  278.                          A5=a/10;
  279.                          a=a%10;
  280.                          A6=a;
  281.                       }
  282.                   else  
  283.                       {
  284.                          A5=0;
  285.                          A6=a;
  286.                       }
  287.                   if(b>=10)
  288.                       {
  289.                          A7=b/10;
  290.                          b=b%10;
  291.                          A8=b;
  292.                       }
  293.                   else
  294.                       {
  295.                          A7=0;
  296.                          A8=b;
  297.                       }
  298.                 }
  299.                 mah[4]=A4;
  300.              mah[3]=A5;
  301.              mah[2]=A6;
  302.              mah[1]=A7;
  303.              mah[0]=A8;
  304. }
  305. //------------------------------
  306. void start(void)       //停止条件是 SCK=1 时,SDA 由 1 到 0
  307. {
  308. SDA=1;
  309. delay(4);
  310. SCK=1;
  311. delay(4);
  312. SDA=0;
  313. delay(4);
  314. SCK=0;
  315. delay(4);
  316. }
  317. //------------------------------
  318. void stop(void)        //停止条件是 SCK=1 时,SDA 由 0 到 1
  319. {
  320. SCK=0;
  321. delay(4);
  322. SDA=0;
  323. delay(4);
  324. SCK=1;
  325. delay(4);
  326. SDA=1;
  327. }
  328. //---------发送一个字节---------
  329. void SendByte(uchar number)
  330. {
  331. uchar i,n,dat;
  332. n=Nack_number;       //可以重发次数
  333.     Send_again:
  334. dat=number;
  335. for(i=0;i<8;i++)       //8 位依次发送
  336. {
  337.   if(dat&0x80)         //取最高位
  338.   {
  339.    bit_out=1;         // 发 1
  340.   }
  341.   else
  342.   {
  343.    bit_out=0;         // 发 0
  344.   }   
  345.   send_bit();          //发送一个位
  346.   dat=dat<<1;          //左移一位
  347. }  
  348. read_bit();          //接收 1 位 应答信号
  349. if(bit_in==1)           //无应答时重发
  350. {
  351.   stop();
  352.   if(n!=0)
  353.   {
  354.    n--;          //可以重发 Nack_number=10 次
  355.    goto Repeat;     // 重发
  356.   }
  357.   else
  358.   {
  359.    goto exit;      // 退出
  360.   }   
  361. }
  362. else
  363. {
  364.   goto exit;
  365. }   
  366. Repeat:
  367. start();        //重新开始
  368. goto Send_again;      // 重发
  369. exit: ;         // 退出
  370. }
  371. //-----------发送一个位---------
  372. void send_bit(void)
  373. {
  374. if(bit_out==1)
  375. {
  376.   SDA=1;          // 发 1
  377. }  
  378. else
  379. {
  380.   SDA=0;          // 发 0
  381. }
  382. _nop_();
  383. SCK=1;           // 上升沿
  384. delay(4);delay(4);
  385. SCK=0;
  386. delay(4);delay(4);
  387. }
  388. //----------接收一个字节--------
  389. uchar ReadByte(void)
  390. {
  391. uchar i,dat;
  392. dat=0;         // 初值为 0
  393. for(i=0;i<8;i++)
  394. {
  395.   dat=dat<<1;       // 左移
  396.   read_bit();       //接收一位
  397.   if(bit_in==1)
  398.   {
  399.    dat=dat+1;      // 为 1 时对应位加 1
  400.   }   
  401. }
  402. SDA=0;         //发送应答信号 0
  403. send_bit();
  404. return dat;        //带回接收数据
  405. }
  406. //----------接收一个位----------
  407. void read_bit(void)
  408. {
  409. SDA=1;         //数据端先置 1
  410. bit_in=1;
  411. SCK=1;         // 上升沿
  412. delay(4);delay(4);
  413. bit_in=SDA;        // 读数据
  414. _nop_();
  415. SCK=0;
  416. delay(4);delay(4);
  417. }


  418. //------------------------------
  419. uint readtemp(void)
  420. {
  421. SCK=0;
  422. start();         //开始条件
  423. SendByte(0x00);       //发送从地址 00
  424. SendByte(0x07);       //发送命令
  425. start();         //开始条件
  426. SendByte(0x01);       //读从地址 00
  427. bit_out=0;
  428. tempL=ReadByte();      //读数据低字节
  429. bit_out=0;
  430. tempH=ReadByte();      //读数据高字节
  431. bit_out=1;
  432. err=ReadByte();       //读错误信息码
  433. stop();         //停止条件
  434. return(tempH*256+tempL);
  435. }
  436. //******************LCD 显示子函数***********************
  437. void init1602(void)       //初始化 LCD
  438. {
  439. cmd_wrt(0x01);       // 清屏
  440. cmd_wrt(0x0c);       //开显示,不显示光标,不闪烁
  441. cmd_wrt(0x06);       //完成一个字符码传送后,光标左移,显 示不发生移位
  442. cmd_wrt(0x38);       //16 ×2 显示,5×7 点阵,8 位数据接口
  443. }
  444. void busy(void)        //LCD忙标志判断
  445. {
  446. flag=0x80;        // 赋初值 高位为 1 禁止
  447. while(flag&0x80)      //读写操作使能位禁止时等待 继续检测
  448. {
  449.   P1=0xff;
  450.   RS=0;         //指向地址计数器
  451.   RW=1;         // 读
  452.   LCDE=1;        //信号下降沿有效
  453.   flag=P1;       //读状态位 高位为状态
  454.   LCDE=0;
  455. }
  456. }
  457. void cmd_wrt(uchar cmd)      //写命令子函数
  458. {
  459. LCDE=0;
  460. busy();         //检测 读写操作使能吗
  461. P1=cmd;         // 命令
  462. RS=0;          //指向命令计数器
  463. RW=0;          // 写
  464. LCDE=1;         //高电平有效
  465. LCDE=0;
  466. }
  467. void dat_wrt(uchar dat)      //写数据子函数
  468. {
  469. busy();         //检测 读写操作使能吗
  470. LCDE=0;
  471. if(flag==16)
  472. {   
  473.   RS=0;        //指向指令寄存器   
  474.   RW=0;         // 写
  475.   P1=0XC0;       //指向第二行
  476.   LCDE=1;        //高电平有效
  477.   LCDE=0;
  478. }  
  479. RS=1;         //指向数据寄存器
  480. RW=0;          // 写
  481. P1=dat;         // 写数据
  482. LCDE=1;         //高电平有效
  483. LCDE=0;
  484. }
  485. //------------延时--------------
  486. void delay(uint n)
  487. {
  488. uint j;
  489. for(j=0;j
  490. {
  491.   _nop_();
  492. }
  493. }

  494. //------------定时器初始化函数----------------
  495. void initInt()
  496. {
  497. TMOD = 0x10;       // 定时器 1 方式 1
  498. TH1=(65536-1000)/256;     //定时器 1 设置 1ms 定时
  499. TL1=(65536-1000)%256;
  500.     EA=1;                              //开总中断                          
  501. ET1 = 1;                          //开定时器 T1 中断   
  502. TR1 = 1;                             //启动定时器 T1
  503. }

  504. //------------定时器中断处理函数-------------------
  505. void timer1handle() interrupt 3   //定时器 3 1ms 中断
  506. {
  507. TH1=(65536-1000)/256;
  508. TL1=(65536-1000)%256;
  509. c20ms++;
  510. c100ms++;
  511. if(c20ms >= 20)    //20ms 计时器
  512.     {
  513.         c20ms = 0;      
  514.         b20ms = 1;
  515.     }
  516. if(c100ms >= 50)    //100ms 计时器
  517.     {
  518.         c100ms = 0;      
  519.         b100ms = 1;
  520.     }
  521. }

  522. //--------------------------温度显示函数------------------------
  523. void show()     
  524. {      
  525. DPY1=0;  
  526. P2=LED01[mah[3]];           //转换 8 位数显示,不带小数点的
  527. delay1(2);
  528. P2=0xFF;
  529.     DPY1=1;

  530. DPY2=0;  
  531. P2=LED02[mah[2]];            //转换 8 位数显示,带小数点的  
  532. delay1(2);
  533. P2=0xFF;
  534.     DPY2=1;

  535. DPY3=0;  
  536. P2=LED01[mah[1]];            //转换 8 位数显示,不带小数点的
  537. delay1(2);
  538.     P2=0xFF;
  539.     DPY3=1;   
  540. }


  541. void ReadKey(void)
  542. {
  543.     row1=0;           //矩阵键盘第 1 列,将第一列拉低,扫描是否有按键按下,第一列按键包 括:1,4,7
  544.     row2=1;           //矩阵键盘第 2 列
  545.     row3=1;           //矩阵键盘第 3 列
  546.     cow1=1;           //矩阵键盘第 1 行  
  547.     cow2=1;           //矩阵键盘第 2 行
  548.     cow3=1;           //矩阵键盘第 3 行
  549. _nop_();          //延时函数
  550. if(!(cow1&cow2&cow3)) //如果有键按下,就返回,且判断是那个键值,否则继续扫描下 一列
  551. {
  552. if(cow1==0)
  553. key_num=1;
  554.     if(cow2==0)
  555. key_num=4;
  556. if(cow3==0)
  557. key_num=7;
  558. return;
  559. }

  560.     row1=1;           //矩阵键盘第 1 列,将第一列拉低,扫描是否有按键按下,第一列按键包 括:2,5,8
  561.     row2=0;           //矩阵键盘第 2 列
  562.     row3=1;           //矩阵键盘第 3 列
  563.     cow1=1;           //矩阵键盘第 1 行  
  564.     cow2=1;           //矩阵键盘第 2 行
  565.     cow3=1;           //矩阵键盘第 3 行
  566. _nop_();          //延时函数
  567. if(!(cow1&cow2&cow3)) //如果有键按下,就返回,且判断是那个键值,否则继续扫描下 一列
  568. {
  569. if(cow1==0)
  570. key_num=2;
  571.     if(cow2==0)
  572. key_num=5;
  573. if(cow3==0)
  574. key_num=8;
  575. return;
  576. }

  577. row1=1;           //矩阵键盘第 1 列,将第一列拉低,扫描是否有按键按下,第一列按键包 括:3,6
  578.     row2=1;           //矩阵键盘第 2 列
  579.     row3=0;           //矩阵键盘第 3 列
  580.     cow1=1;           //矩阵键盘第 1 行  
  581.     cow2=1;           //矩阵键盘第 2 行
  582. _nop_();          //延时函数
  583. if(!(cow1&cow2)) //如果有键按下,就返回,且判断是那个键值,否则继续扫描下一列
  584. {
  585. if(cow1==0)
  586. key_num=3;
  587.     if(cow2==0)
  588. key_num=6;
  589. return;
  590. }
  591. }
  592. //--------------数码管显示延时函数-----------------------------------------------------
  593. void delay1(uint z)
  594. {
  595.   uint x,y;
  596.   for(x=z;x>0;x--)
  597.   for(y=110;y>0;y--);
  598. }
  • 三极管的主要参数 1.直流参数
    (1)集电极一基极反向饱和电流Icbo,发射极开路(Ie=0)时,基极和集电极之间加上规定的反向电压Vcb时的集电极反向电流,它只与温度有关,在一定温度下是个常数,所以称为集电

  • 推荐资讯
    相关文章
    栏目更新
    栏目热门
    关于我们
    电脑周边
    家用电器
    通讯
    地区
    新闻中心
    深圳贴片加工厂
     
    • ☆电源板
    • ☆U盘
    • ☆网卡
    • ☆显卡
    • ☆监控摄像头
    • ☆电脑主板
    • ☆平板电脑主板
    • ☆DVD主板
    • 解码板
    • 伺服板
    • 高频头板
    • 复读机板
    • 音响主板
    • ☆手机主板
    • ☆手机按键板
    • ☆无线电话机
    • ☆对讲机主板
    • ☆深圳
    • 东莞
    • 广州
    • 龙岗
    • 宝安
    • 龙华
    • 坂田