|
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ì)此描述如下.

- /*硬件連接*/
- // PC0<--->SDA PC1---->SCL
- /****************************************************************************************
- *開發(fā)環(huán)境:IAR for stm8 v6.5.3
- *硬件平臺(tái):STM8L-DISCOVERY
- *功能說明:通過硬件I2C等待的方法,實(shí)現(xiàn)對(duì)24C02寄存器的讀寫,借助IAR軟件的調(diào)試功能,查看變量的數(shù)值
- *作 者:茗風(fēng)
- ****************************************************************************************/
- #include"iostm8l152c6.h"
- #include"stdbool.h"
- #include"stdint.h"
- #define _5NOPS asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop")//用于I2C讀寫延時(shí)
- /******************************************************************************************************
- * 名 稱:void delay_10ms(uint8_t x_ms)
- * 功 能:延時(shí)10ms
- * 入口參數(shù):無
- * 出口參數(shù):無
- * 說 明:
- * 范 例:無
- ******************************************************************************************************/
- void delay_100ms(void)
- {
- uint8_t i,j;
- for(i=0;i<255;i++)//2*255個(gè)指令周期
- for(j=0;j<255;j++);//2*255個(gè)指令周期
- // delay_10ms共消耗 x_ms*2*255+2*x_ms個(gè)指令周期
- // 255*2*255+2*255=130610us=130ms
- // 此延時(shí)函數(shù),延時(shí)時(shí)間為130ms
- // 16M/8/2=1M 一個(gè)指令周期為1us
- }
- /******************************************************************************************************
- * 名 稱: uint8_t I2C_ReadOneByteDataFromSlave(uint8_t address)
- * 功 能:從I2C從設(shè)備中讀取一字節(jié)的數(shù)據(jù)
- * 入口參數(shù):address:讀取數(shù)據(jù)的寄存器地址
- * 出口參數(shù):返回一個(gè)從I2C從設(shè)備指定地址讀到的數(shù)據(jù)
- * 說 明:
- * 范 例:無
- ******************************************************************************************************/
- uint8_t I2C_ReadOneByteDataFromSlave(uint8_t address)
- {
- volatile uint8_t t;
-
- //----------I2C起始信號(hào)--------------
- I2C1_CR2_START=1;//產(chǎn)生一個(gè)起始條件
- while(!(I2C1_SR1_SB==1));//讀SR1寄存器,清除SB標(biāo)志位
- _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)
-
- //-------發(fā)送寫I2C從器件地址---------
- I2C1_DR=0xA0;//發(fā)送從設(shè)備地址
- while(!(I2C1_SR1_ADDR==1));//讀SR1寄存器,清除ADDR標(biāo)志位
- _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)
- if(I2C1_SR3_TRA==0)return 1;//讀SR3寄存器,清除ADDR標(biāo)志位
- // 0: Data bytes received
- // 1: Data bytes transmitted
-
- //-----寫I2C從器件寄存器地址--------
- I2C1_DR=address;
- while(!(I2C1_SR1_BTF==1));//等待地址發(fā)送完成
- _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)
-
- //--------I2C重復(fù)起始信號(hào)-----------
- I2C1_CR2_START=1;//重復(fù)產(chǎn)生一個(gè)起始條件
- while(!(I2C1_SR1_SB==1));//讀SR1寄存器,清除SB標(biāo)志位
- _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)
-
- //-------發(fā)送讀I2C從器件地址---------
- I2C1_DR=0xA1;//發(fā)送從設(shè)備地址
- while(!(I2C1_SR1_ADDR==1));//讀SR1寄存器,清除ADDR標(biāo)志位
- _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)
- if(I2C1_SR3_TRA==1)return 1;//讀SR3寄存器,清除ADDR標(biāo)志位
- while(!(I2C1_SR1_RXNE==1));//等待地址發(fā)送完成
-
- //-------------停止信號(hào)-------------
- I2C1_CR2_STOP=1;
-
- //-------------讀取數(shù)據(jù)-------------
- t=I2C1_DR;
-
- return t;
- }
- /******************************************************************************************************
- * 名 稱:void I2C_WriteOneByteDataToSlave(uint8_t address,uint8_t dat)
- * 功 能:寫入一字節(jié)的數(shù)據(jù)到I2C設(shè)備中
- * 入口參數(shù):address:寫入的數(shù)據(jù)存儲(chǔ)地址 dat:待寫入的數(shù)據(jù)
- * 出口參數(shù):無
- * 說 明: 通過MSTM8L硬件寫入I2C設(shè)備一個(gè)字節(jié)的數(shù)據(jù)
- * 范 例:無
- ******************************************************************************************************/
- uint8_t I2C_WriteOneByteDataToSlave(uint8_t address,uint8_t dat)
- {
- volatile uint8_t t;
- //----------I2C起始信號(hào)--------------
- I2C1_CR2_START=1;//產(chǎn)生一個(gè)起始條件
- while(!(I2C1_SR1_SB==1));
- _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)
- I2C1_DR=0xA0;
-
- //--------寫I2C從器件地址-----------
- while(!(I2C1_SR1_ADDR==1));
- _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)
- if(I2C1_SR3_TRA==0)return 1;//讀SR3寄存器,清除ADDR標(biāo)志位
-
- //-----寫I2C從器件寄存器地址--------
- while(!(I2C1_SR1_TXE==1));
- I2C1_DR=address;
-
- //-------寫I2C數(shù)據(jù)到寄存器中--------
- while(!(I2C1_SR1_TXE==1));
- I2C1_DR=dat;
- while(!(I2C1_SR1_TXE==1));
- while(!(I2C1_SR1_BTF==1));
- _5NOPS;//根據(jù)數(shù)據(jù)手冊(cè),檢測到標(biāo)志位后,需插入5個(gè)NOP進(jìn)行延時(shí)
-
- //-------------停止信號(hào)-------------
- I2C1_CR2_STOP=1;
- return 0;
- }
- /******************************************************************************************************
- * 名 稱: IIC_init()
- * 功 能:初始化IIC
- * 入口參數(shù):無
- * 出口參數(shù):無
- * 說 明:PC0--SDA PC1--SCL
- * 范 例:無
- ******************************************************************************************************/
- void I2C_Init(void)
- {
- //----打開IIC外設(shè)時(shí)鐘----
- CLK_PCKENR1_PCKEN13=1;//
- I2C1_CR1_PE=0;
-
- //----I2C輸入時(shí)鐘頻率選擇----
- I2C1_FREQR_FREQ=0x02;//2MHz
- /* The allowed range is between 1 MHz and 16 MHz
- 000000: not allowed
- 000001: 1 MHz
- 000010: 2 MHz
- ...
- 010000: 16 MHz */
-
- //----配置時(shí)鐘控制寄存器----
- I2C1_CCRH_F_S=0; //Standard mode I2C
- I2C1_CCRL=10; //SCK低電平時(shí)間配置
- //I2C的SCK時(shí)鐘設(shè)置為100KHz,則SCK周期為10us
- //因?yàn)镮2C1_FREQR_FREQ=0x02,即I2C輸入時(shí)鐘頻率為2M,周期為0.5us
- //CCR=10時(shí),SCK的低電平時(shí)間為tlow=10*0.5us=5us,SCk高電平時(shí)間為thigh=10*0.5us=5us
- //所以CCR=10時(shí),SCK輸出頻率為100KHz
-
- //----配置上升時(shí)間寄存器----
- I2C1_TRISER_TRISE=3;//in standard mode, the maximum allowed SCL rise time is 1000 ns.
- //1 us / 0.5 us = 2 + 1
- I2C1_CR1_PE=1;//
-
- }
- void main(void)
- {
- static uint8_t tmp=0;
- I2C_Init();
- // asm("rim"); //enable interrupts
- I2C_WriteOneByteDataToSlave(0x02,0x84);
- delay_100ms();
- tmp=I2C_ReadOneByteDataFromSlave(0x02);
- asm("nop");
- while(1)
- {
- asm("wfi");
- }
- }
復(fù)制代碼
|
|