找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 22523|回復(fù): 1
收起左側(cè)

STM8L的I2C基本讀寫方法詳解 含例程

[復(fù)制鏈接]
ID:140343 發(fā)表于 2016-10-10 00:52 | 顯示全部樓層 |閱讀模式
STM8L的硬件I2C支持100KHz~400KHz的讀寫速度,作為主設(shè)備使用時(shí),不需要配置IO,開啟I2C硬件后,對(duì)應(yīng)的IO會(huì)自動(dòng)啟用復(fù)用功能。本文選取24C02作為I2C從設(shè)備,STM8L作為主設(shè)備,進(jìn)行I2C讀寫功能測試。
STM8L作為I2C主設(shè)備時(shí),官方的數(shù)據(jù)手冊(cè)給出的配置流程如下圖:

詳細(xì)配置I2C為主設(shè)備的流程如下:

①打開I2C外設(shè)時(shí)鐘
②I2C輸入時(shí)鐘頻率大小選擇
③配置時(shí)鐘控制寄存器
④配置上升沿時(shí)間寄存器
⑤開啟I2C功能


STM8L的I2C默認(rèn)為從設(shè)備,當(dāng)發(fā)送一個(gè)START信號(hào)后,自動(dòng)從從模式轉(zhuǎn)成主模式.

STM8L的I2C的實(shí)現(xiàn)寫一字節(jié)的描述如下:
①CR2寄存器中的START位被置位后,發(fā)送一個(gè)起始信號(hào),SR1中的SB被硬件置位.讀取SR1寄存器,清除該標(biāo)志位.
②向DR寄存器寫入從設(shè)備地址,SR1中的ADDR會(huì)被硬件置位,通過讀SR1,然后再讀SR3,清除該標(biāo)志位.
③DR寄存器為空后,將從設(shè)備寄存器地址寫入DR
④DR寄存器為空后,將從要寫入的數(shù)據(jù)寫入DR
STM8L讀取一字節(jié)數(shù)據(jù),這里不在贅述.
注意:I2C的時(shí)鐘頻率為2M以下時(shí),根據(jù)數(shù)據(jù)手冊(cè),在檢測到SB,ADDR,BTF,這些標(biāo)志位后,必須在其后插入5個(gè)NOP再清除標(biāo)志位.


STM8S中文文檔中,對(duì)此描述如下.


  1. /*硬件連接*/

  2. // PC0<--->SDA   PC1---->SCL

  3. /****************************************************************************************

  4. *開發(fā)環(huán)境:IAR for stm8 v6.5.3

  5. *硬件平臺(tái):STM8L-DISCOVERY

  6. *功能說明:通過硬件I2C等待的方法,實(shí)現(xiàn)對(duì)24C02寄存器的讀寫,借助IAR軟件的調(diào)試功能,查看變量的數(shù)值

  7. *作    者:茗風(fēng)

  8. ****************************************************************************************/

  9. #include"iostm8l152c6.h"

  10. #include"stdbool.h"

  11. #include"stdint.h"


  12. #define  _5NOPS     asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop")//用于I2C讀寫延時(shí)

  13. /******************************************************************************************************

  14. *  名    稱:void delay_10ms(uint8_t x_ms)

  15. *  功    能:延時(shí)10ms

  16. *  入口參數(shù):無

  17. *  出口參數(shù):無

  18. *  說    明:

  19. *  范    例:無

  20. ******************************************************************************************************/

  21. void delay_100ms(void)

  22. {

  23.   uint8_t i,j;

  24.   for(i=0;i<255;i++)//2*255個(gè)指令周期

  25.     for(j=0;j<255;j++);//2*255個(gè)指令周期

  26.   // delay_10ms共消耗 x_ms*2*255+2*x_ms個(gè)指令周期  

  27.   // 255*2*255+2*255=130610us=130ms

  28.   // 此延時(shí)函數(shù),延時(shí)時(shí)間為130ms

  29.   // 16M/8/2=1M 一個(gè)指令周期為1us

  30. }

  31. /******************************************************************************************************

  32. * 名 稱: uint8_t I2C_ReadOneByteDataFromSlave(uint8_t address)

  33. * 功 能:從I2C從設(shè)備中讀取一字節(jié)的數(shù)據(jù)

  34. * 入口參數(shù):address:讀取數(shù)據(jù)的寄存器地址

  35. * 出口參數(shù):返回一個(gè)從I2C從設(shè)備指定地址讀到的數(shù)據(jù)

  36. * 說 明:

  37. * 范 例:無

  38. ******************************************************************************************************/

  39. uint8_t I2C_ReadOneByteDataFromSlave(uint8_t address)

  40. {

  41.   volatile uint8_t t;

  42.   

  43.   //----------I2C起始信號(hào)--------------

  44.   I2C1_CR2_START=1;//產(chǎn)生一個(gè)起始條件

  45.   while(!(I2C1_SR1_SB==1));//讀SR1寄存器,清除SB標(biāo)志位

  46.   _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)

  47.   

  48.   //-------發(fā)送寫I2C從器件地址---------

  49.   I2C1_DR=0xA0;//發(fā)送從設(shè)備地址

  50.   while(!(I2C1_SR1_ADDR==1));//讀SR1寄存器,清除ADDR標(biāo)志位

  51.   _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)

  52.   if(I2C1_SR3_TRA==0)return 1;//讀SR3寄存器,清除ADDR標(biāo)志位

  53.   //  0: Data bytes received

  54.   //  1: Data bytes transmitted

  55.   

  56.   //-----寫I2C從器件寄存器地址--------

  57.   I2C1_DR=address;

  58.   while(!(I2C1_SR1_BTF==1));//等待地址發(fā)送完成

  59.   _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)

  60.   

  61.   //--------I2C重復(fù)起始信號(hào)-----------

  62.   I2C1_CR2_START=1;//重復(fù)產(chǎn)生一個(gè)起始條件

  63.   while(!(I2C1_SR1_SB==1));//讀SR1寄存器,清除SB標(biāo)志位

  64.   _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)

  65.   

  66.   //-------發(fā)送讀I2C從器件地址---------

  67.   I2C1_DR=0xA1;//發(fā)送從設(shè)備地址

  68.   while(!(I2C1_SR1_ADDR==1));//讀SR1寄存器,清除ADDR標(biāo)志位

  69.   _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)

  70.   if(I2C1_SR3_TRA==1)return 1;//讀SR3寄存器,清除ADDR標(biāo)志位

  71.   while(!(I2C1_SR1_RXNE==1));//等待地址發(fā)送完成

  72.   

  73.   //-------------停止信號(hào)-------------

  74.   I2C1_CR2_STOP=1;

  75.   

  76.   //-------------讀取數(shù)據(jù)-------------

  77.   t=I2C1_DR;

  78.   

  79.   return t;

  80. }

  81. /******************************************************************************************************

  82. * 名 稱:void I2C_WriteOneByteDataToSlave(uint8_t address,uint8_t dat)

  83. * 功 能:寫入一字節(jié)的數(shù)據(jù)到I2C設(shè)備中

  84. * 入口參數(shù):address:寫入的數(shù)據(jù)存儲(chǔ)地址    dat:待寫入的數(shù)據(jù)

  85. * 出口參數(shù):無

  86. * 說 明: 通過MSTM8L硬件寫入I2C設(shè)備一個(gè)字節(jié)的數(shù)據(jù)

  87. * 范 例:無

  88. ******************************************************************************************************/

  89. uint8_t I2C_WriteOneByteDataToSlave(uint8_t address,uint8_t dat)

  90. {

  91.   volatile uint8_t t;

  92.   //----------I2C起始信號(hào)--------------

  93.   I2C1_CR2_START=1;//產(chǎn)生一個(gè)起始條件

  94.   while(!(I2C1_SR1_SB==1));

  95.   _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)

  96.   I2C1_DR=0xA0;

  97.   

  98.   //--------寫I2C從器件地址-----------

  99.   while(!(I2C1_SR1_ADDR==1));

  100.   _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)

  101.   if(I2C1_SR3_TRA==0)return 1;//讀SR3寄存器,清除ADDR標(biāo)志位

  102.   

  103.   //-----寫I2C從器件寄存器地址--------

  104.   while(!(I2C1_SR1_TXE==1));

  105.   I2C1_DR=address;

  106.   

  107.   //-------寫I2C數(shù)據(jù)到寄存器中--------

  108.   while(!(I2C1_SR1_TXE==1));

  109.   I2C1_DR=dat;

  110.   while(!(I2C1_SR1_TXE==1));

  111.   while(!(I2C1_SR1_BTF==1));

  112.   _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)

  113.   

  114.   //-------------停止信號(hào)-------------

  115.   I2C1_CR2_STOP=1;

  116.   return 0;

  117. }


  118. /******************************************************************************************************

  119. * 名 稱: IIC_init()

  120. * 功 能:初始化IIC

  121. * 入口參數(shù):無

  122. * 出口參數(shù):無

  123. * 說 明:PC0--SDA   PC1--SCL

  124. * 范 例:無

  125. ******************************************************************************************************/

  126. void I2C_Init(void)

  127. {

  128.   //----打開IIC外設(shè)時(shí)鐘----

  129.   CLK_PCKENR1_PCKEN13=1;//

  130.   I2C1_CR1_PE=0;

  131.   

  132.   //----I2C輸入時(shí)鐘頻率選擇----

  133.   I2C1_FREQR_FREQ=0x02;//2MHz

  134.   /*  The allowed range is between 1 MHz and 16 MHz

  135.   000000: not allowed

  136.   000001: 1 MHz

  137.   000010: 2 MHz

  138.   ...

  139.   010000: 16 MHz                                 */

  140.   

  141.   //----配置時(shí)鐘控制寄存器----

  142.   I2C1_CCRH_F_S=0; //Standard mode I2C

  143.   I2C1_CCRL=10;    //SCK低電平時(shí)間配置

  144.   //I2C的SCK時(shí)鐘設(shè)置為100KHz,則SCK周期為10us

  145.   //因?yàn)镮2C1_FREQR_FREQ=0x02,即I2C輸入時(shí)鐘頻率為2M,周期為0.5us

  146.   //CCR=10時(shí),SCK的低電平時(shí)間為tlow=10*0.5us=5us,SCk高電平時(shí)間為thigh=10*0.5us=5us

  147.   //所以CCR=10時(shí),SCK輸出頻率為100KHz

  148.   

  149.   //----配置上升時(shí)間寄存器----

  150.   I2C1_TRISER_TRISE=3;//in standard mode, the maximum allowed SCL rise time is 1000 ns.

  151.   //1 us / 0.5 us = 2 + 1


  152.   I2C1_CR1_PE=1;//

  153.   

  154. }


  155. void main(void)

  156. {

  157.   static uint8_t tmp=0;

  158.   I2C_Init();

  159. //  asm("rim");               //enable interrupts

  160.   I2C_WriteOneByteDataToSlave(0x02,0x84);

  161.   delay_100ms();

  162.   tmp=I2C_ReadOneByteDataFromSlave(0x02);

  163.   asm("nop");

  164.   while(1)

  165.   {

  166.     asm("wfi");

  167.   }

  168. }
復(fù)制代碼




回復(fù)

使用道具 舉報(bào)

ID:161571 發(fā)表于 2020-5-15 08:55 | 顯示全部樓層
樓主你好,最近也用到這個(gè)8L的單片機(jī),用到了I2C,參考你的代碼復(fù)制,在調(diào)試的時(shí)候就一直卡在這while(!(I2C1_SR1_SB==1)); 示波器上是有SCL時(shí)鐘輸出的,請(qǐng)問下樓主有遇到這樣的情況嗎
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表