日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

基于STM8的IIC协议--实例篇--时钟模块(DS3231)读取

發(fā)布時(shí)間:2023/12/19 综合教程 32 生活家
生活随笔 收集整理的這篇文章主要介紹了 基于STM8的IIC协议--实例篇--时钟模块(DS3231)读取 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 綜述

  由上篇博客可知道IIC協(xié)議如何用代碼實(shí)現(xiàn),本篇博客就不涉及協(xié)議內(nèi)容,只講解如何使用。

  本次的實(shí)驗(yàn)傳感為:DS3231(時(shí)鐘模塊),對(duì)于時(shí)鐘模塊的具體信息我也就不多介紹,大家可以自行度娘,具體功能無(wú)非就是讓單片機(jī)中能夠起到獲取時(shí)間的作用。該模塊是可以由IIC協(xié)議去驅(qū)動(dòng)的,再加上所要的操作也是比較簡(jiǎn)單,部分剛接觸IIC協(xié)議的小伙伴可以拿來(lái)練手的一個(gè)模塊。

2. 明確任務(wù)順序

  個(gè)人習(xí)慣,在每驅(qū)動(dòng)一個(gè)新傳感的時(shí)候,我會(huì)將我要完成的傳感分為幾個(gè)任務(wù)點(diǎn)。接下來(lái)就展示一下我在寫(xiě)DS3231模塊時(shí)的任務(wù)欄。

一.硬件部分
1.完成排針焊接
2.完成傳感引角和單片機(jī)引角的接線
二.軟件部分
1. 找到該傳感的官方手冊(cè)并認(rèn)真閱讀
2. 找到并定義該傳感的地址(7位地址、8位地址)
3. 找到并定義該傳感器的寄存器地址 4. 完成讀寫(xiě)函數(shù)的代碼 5. 測(cè)試傳感是否有響應(yīng)
6. 查看手冊(cè),了解傳感的工作模式
7. 完成傳感參數(shù)初始化 8. 傳感數(shù)據(jù)的獲取

  根據(jù)上面這些小任務(wù)一一解決,這樣一來(lái),大多數(shù)傳感就能成功驅(qū)動(dòng)了,這里在給一個(gè)建議,驅(qū)動(dòng)傳感器的代碼最好不要一次性全部寫(xiě)完再進(jìn)行測(cè)試,這樣成功率不高,并且會(huì)大大增加你找問(wèn)題的難度,將每個(gè)功能函數(shù)測(cè)試完再進(jìn)行下一個(gè)功能函數(shù)的編寫(xiě),會(huì)大大加大你的效率。

3. 具體任務(wù)實(shí)現(xiàn)步驟

  3.1. 硬件部分

  在STM8S103芯片中,我所定義的IIC協(xié)議中的SDA引角為PD3,SCL引角為PD4,該時(shí)鐘模塊所需提供的電源為3.3V。所以接線圖如下。

  

  3.2. 軟件部分

 (1)官方手冊(cè)

  我這里提供的是全英版的官方手冊(cè),多看點(diǎn)英文對(duì)你有好處的。

鏈接:https://pan.baidu.com/s/1Oo6o68SoVr7gt8tPZIoQxw 
提取碼:uzih 

  (2)器件地址

  在說(shuō)明手冊(cè)中,我們可以在第16頁(yè)的右下角找到下面這句話:

  The slave address byte contains the 7-bit DS3231 address, which is 1101000, followed by the direction bit (R/W), which is 0 for a write.

  這句話的大意為,從機(jī)的7位地址為1101000,后跟一位讀寫(xiě)位,讀寫(xiě)位為0時(shí)是寫(xiě)位。即7位地址的為0x68,8位地址為0xD0。

  (3)寄存器地址

  

  DS3231的寄存器地址都在這了,大家可根據(jù)所需要用的功能定義相應(yīng)的寄存器。

  以下是我在頭文件所定義的格式,因?yàn)槲抑恍枰@取時(shí)間,不需要進(jìn)行其他操作,所以部分寄存器沒(méi)有使用。

1 #define DS3231_Address           0xD0                           //設(shè)備地址
2 #define Seconds_Register         0x00                           //秒鐘寄存器
3 #define Minutes_Register         0x01                           //分鐘寄存器
4 #define Hour_Register            0x02                           //小時(shí)寄存器
5 #define Day_Register             0x03                           //星期寄存器
6 #define Date_Register            0x04                           //日期寄存器
7 #define Month_Register           0x05                           //月份寄存器(第七位是世紀(jì)位)
8 #define Year_Register            0x06                           //年份寄存器

4. 例程

4.1 編譯環(huán)境

  我的編譯環(huán)境是IAR,這款軟件是現(xiàn)在STM8的主流平臺(tái),比較推薦。不過(guò)我打算等到STCubeMX更新出比較方便的版本后再去使用Keil5,因?yàn)槲以谟肧TM32的時(shí)候就是利用Keil5,的確很方便,你們也可以學(xué)著用一下。

4.2 主芯片

  我的主芯片是STM8S系列中的103,其中STM8S的003、005、和103、105,配置一樣(外設(shè)和CPU頻率,F(xiàn)LASH),在代碼相同的情況下均可進(jìn)行燒寫(xiě)。

4.3 庫(kù)文件的添加

  我們的工程可以在IAR中的官方例程中復(fù)制,操作過(guò)程:打開(kāi)STM8S_StdPeriph_Lib(這是一個(gè)官方的庫(kù)文件,下載IAR STM8包的時(shí)候就攜帶,里面有庫(kù)文件和相對(duì)應(yīng)的例程),將Libraries文件復(fù)制到你工程所在的文件下,并將有關(guān)于ADC的庫(kù)文件添加到你的工程列表當(dāng)中。添加完成后,就可以開(kāi)始編寫(xiě)代碼了(如果你將全部的庫(kù)文件都添加進(jìn)來(lái)的話,編譯程序后庫(kù)文件還有紅點(diǎn)報(bào)錯(cuò)的話,這是因?yàn)槟氵x的芯片上沒(méi)有該功能,你需要將其刪掉才能不報(bào)錯(cuò)。)如圖。

4.4 代碼

4.4.1 SDA、SCL引角的定義

  我這里將SDA、SCL都設(shè)置為了推挽輸出,具體為什么可與參考上一片IIC協(xié)議講解。

1   //IIC引腳 
2   GPIO_Init(IIC_SCL_GPIO_Port, IIC_SCL_Pin, GPIO_MODE_OUT_PP_HIGH_FAST);
3   GPIO_Init(IIC_SDA_GPIO_Port, IIC_SDA_Pin, GPIO_MODE_OUT_PP_HIGH_FAST);

4.4.2 DS3231句柄定義

  為了能夠方便數(shù)據(jù)的管理,所以我定義了DS3231的一個(gè)句柄。

 1 typedef struct DS3231
 2 {    
 3   uint8_t uSeconds;                     //秒
 4   uint8_t uMinutes;                     //分鐘
 5   uint8_t uHour;                        //小時(shí)
 6   uint8_t uDay;                         //星期
 7   uint8_t uData;                        //日期
 8   uint8_t uMouth;                       //月份
 9   uint8_t uyear;                        //年份
10   uint8_t uTime[3];                     //將秒、分鐘、小時(shí)、日期包括在內(nèi)
11   
12     
13 }DS3231_HandleTypeDef; 

4.4.3 BCD格式和B格式轉(zhuǎn)換

  在手冊(cè)中可以看到,寫(xiě)入到DS3231中的格式是BCD格式,而讀取到的卻是B格式,所以我們需要兩個(gè)函數(shù)將其轉(zhuǎn)換,也方便我們察看數(shù)據(jù)的結(jié)果。

 1 uint8_t Byte_Transform_BCD(uint8_t uData)
 2 {
 3   uint8_t i, j, uBCD_Code;
 4   
 5   i = uData / 10;
 6   j = uData % 10;
 7   uBCD_Code = j + ( i << 4 );
 8   
 9   return uBCD_Code;
10   
11 }
12 
13 uint8_t BCD_Transform_Byte(uint8_t uData)
14 {
15     uint8_t uByte_Code;
16 
17     uByte_Code  = (uData & 0x0f);
18     uData     >>= 4;
19     uData      &= 0x0f;
20     uData      *= 10;
21     uByte_Code += uData;
22 
23     return uByte_Code;
24     
25 }

4.4.4讀寫(xiě)函數(shù)編寫(xiě)

  讀寫(xiě)函數(shù)我們?nèi)绻蝗タ词謨?cè)說(shuō)明的話是無(wú)法編寫(xiě)代碼的,所以我們需要去看手冊(cè),根據(jù)手冊(cè)中的IIC命令順序進(jìn)行編寫(xiě)代碼。

    這幅圖為 IIC數(shù)據(jù)傳輸概述。

    寫(xiě)函數(shù)流程圖:

    

  這個(gè)流程圖是在DS3231中的官方圖,根據(jù)圖中的命令可以寫(xiě)出代碼,其中,代碼中出現(xiàn)IIC_HandleTypedef * iicHandle等參數(shù),是IIC的句柄,具體可看上一篇博客,下面所出現(xiàn)的也是一樣的意思。

 1 uint8_t vSen_DS3231_Write_Bytes(IIC_HandleTypedef * iicHandle, uint8_t Register_Address, uint8_t Data_Byte)
 2 {
 3   
 4   vIIC_Start_Signal(iicHandle);                                                 //1.  IIC_Start                 ;  起始信號(hào)                               
 5   vIIC_SendByte(iicHandle, Slave_Address);                                      //2.  IIC_Send Device Address(W);  發(fā)送(設(shè)備地址)告訴總線即將操作的設(shè)備   
 6   
 7   if(!bIIC_ReadACK(iicHandle))                                                  //3.  IIC_ReadAck               ;  等待響應(yīng)
 8   {                                                                                   
 9     vIIC_Stop_Signal(iicHandle);                                                   
10     return FALSE;                                                                     
11   }
12   
13   vIIC_SendByte(iicHandle, Register_Address);                                   //4.  IIC_Send Register Address ; 發(fā)送(寄存器)   告訴設(shè)備我們即將操作的寄存器
14   bIIC_ReadACK(iicHandle);                                                      //5.  IIC_ReadAck               ; 等待響應(yīng)
15   vIIC_SendByte(iicHandle, Data_Byte);                                          //6.  IIC_Send the data to Reg  ; 發(fā)送(數(shù)據(jù))     寫(xiě)入數(shù)據(jù)到指定設(shè)備的寄存器中
16   bIIC_ReadACK(iicHandle);                                                      //7.  IIC_ReadAck               ; 等待響應(yīng)
17   vIIC_Stop_Signal(iicHandle);                                                  //8.  IIC_Stop                  ; 結(jié)束信號(hào)
18   
19 
20   return TRUE;
21   
22 }

  讀函數(shù)流程圖:

 1 uint8_t vSen_DS3231_Read_Bytes(IIC_HandleTypedef * iicHandle, uint8_t Register_Address)
 2 {
 3   uint8_t uRev_Register_Data = 0x00;
 4   
 5   vIIC_Start_Signal(iicHandle);                                                 //1.  IIC_Start                 ;  起始信號(hào)                                                                                                                                                  
 6   vIIC_SendByte(iicHandle, Slave_Address);                                      //2.  IIC_Send Device Address(W);  發(fā)送(設(shè)備地址)告訴總線即將操作的設(shè)備       
 7                                                                                          
 8   if(!bIIC_ReadACK(iicHandle))                                                  //3.  IIC_ReadAck               ;  等待響應(yīng)
 9   {                                                                                      
10     vIIC_Stop_Signal(iicHandle);                                                      
11     return FALSE;                                                                        
12   }                                                                                      
13                                                                                          
14   vIIC_SendByte(iicHandle, Register_Address);                                   //4.  IIC_Send Register Address ; 發(fā)送(寄存器)   告訴設(shè)備我們即將操作的寄存器
15   vIIC_Ack(iicHandle);                                                          //5.  IIC_Ack                   ; 主動(dòng)響應(yīng)
16   vIIC_Start_Signal(iicHandle);                                                 //6.  IIC_Start ; 起始信號(hào)
17 vIIC_SendByte(iicHandle, Slave_Address+1); //7. IIC_Send Device Address(R); 發(fā)送(設(shè)備地址)告訴總線即將操作的設(shè)備 18 vIIC_Ack(iicHandle); //8. IIC_Ack ; 主動(dòng)響應(yīng) 19 uRev_Register_Data = uIIC_RecvByte(iicHandle); //9. IIC_ReadByte ; 讀取寄存器中的數(shù)據(jù) 20 vIIC_NAck(iicHandle); //10. IIC_Nack ; 主動(dòng)不應(yīng)答 21 vIIC_Stop_Signal(iicHandle); //11. IIC_Stop ; 結(jié)束信號(hào) 22 23 return uRev_Register_Data; 24 25 }

  

  完成讀寫(xiě)函數(shù)的編寫(xiě)后,那么我們就可測(cè)試傳感是否通信成功,具體可檢測(cè)的方法有挺多,最直觀的是用示波器察看波形,若在讀寫(xiě)函數(shù)發(fā)送器件地址后,有接下來(lái)的發(fā)送寄存器地址和數(shù)據(jù)等操作波形的話,即有返回到ACK,則單片機(jī)與傳感通信成功。這里再說(shuō)一個(gè)不需要用到的示波器的操作,同樣的,在讀寫(xiě)函數(shù)發(fā)送器件地址后,用Uart發(fā)送功能,在串口助手上打印一個(gè)數(shù),若有數(shù)顯示,則沒(méi)有return 跳出函數(shù),證明SDA的電平被器件拉低,也是有ACK返回的情況,則單片機(jī)于傳感通信成功。

4.4.5 修改時(shí)間

  我們?cè)谧x取時(shí)間之前需要對(duì)時(shí)間進(jìn)行一個(gè)手動(dòng)輸入的方法去給予時(shí)鐘模塊一個(gè)初始值,這樣才能開(kāi)始計(jì)時(shí),這個(gè)函數(shù)可以當(dāng)作修改時(shí)間的功能,具體代碼可以自行編寫(xiě),我這里的代碼就寫(xiě)成全部修改。

 1 void vSen_DS3231_Modify_Time(IIC_HandleTypedef * iicHandle, uint8_t uyear, uint8_t uMouth, uint8_t uData, uint8_t uDay, uint8_t uHour, uint8_t uMinutes, uint8_t uSeconds)
 2 {
 3 
 4   vSen_DS3231_Write_Bytes(iicHandle, Year_Register,    Byte_Transform_BCD(uyear));                //修改年份
 5                   
 6   vSen_DS3231_Write_Bytes(iicHandle, Month_Register,   Byte_Transform_BCD(uMouth));               //修改月份
 7                   
 8   vSen_DS3231_Write_Bytes(iicHandle, Date_Register,    Byte_Transform_BCD(uData));                //修改日期
 9       
10   vSen_DS3231_Write_Bytes(iicHandle, Day_Register,     Byte_Transform_BCD(uDay));                 //修改星期
11       
12   vSen_DS3231_Write_Bytes(iicHandle, Hour_Register,    Byte_Transform_BCD(uHour));                //修改小時(shí)
13                   
14   vSen_DS3231_Write_Bytes(iicHandle, Minutes_Register, Byte_Transform_BCD(uMinutes));             //修改分鐘
15             
16   vSen_DS3231_Write_Bytes(iicHandle, Seconds_Register, Byte_Transform_BCD(uSeconds));             //修改秒鐘
17   
18 }

4.4.6 獲取時(shí)間

  獲取時(shí)間就直接讀取相應(yīng)的寄存器獲取數(shù)值即可,最后將其輸出就行。

 1 void vSen_DS3231_Get_Times(IIC_HandleTypedef * iicHandle, DS3231_HandleTypeDef * hDS3231)
 2 {
 3   hDS3231->uyear    =  BCD_Transform_Byte(vSen_DS3231_Read_Bytes(iicHandle, Year_Register));      //獲取年份
 4 
 5   hDS3231->uMouth   =  BCD_Transform_Byte(vSen_DS3231_Read_Bytes(iicHandle, Month_Register));     //獲取月份 
 6   
 7   hDS3231->uData    =  BCD_Transform_Byte(vSen_DS3231_Read_Bytes(iicHandle, Date_Register));      //獲取日期  
 8   
 9   hDS3231->uDay     =  BCD_Transform_Byte(vSen_DS3231_Read_Bytes(iicHandle, Day_Register));       //獲取星期  
10   
11   hDS3231->uHour    =  BCD_Transform_Byte(vSen_DS3231_Read_Bytes(iicHandle, Hour_Register));      //獲取小時(shí)   
12      
13   hDS3231->uMinutes =  BCD_Transform_Byte(vSen_DS3231_Read_Bytes(iicHandle, Minutes_Register));   //獲取分鐘
14   
15   hDS3231->uSeconds =  BCD_Transform_Byte(vSen_DS3231_Read_Bytes(iicHandle, Seconds_Register));   //獲取秒鐘  
16                                                                               
17 }

4.4.7 DS3231初始化

 1 /*******************************************************************************
 2 * Function Name  : vSen_DS3231_IIC_Init
 3 * Description    : DS3231 Init
 4 * Input          : IIC_HandleTypedef * iicHandle, GPIO_TypeDef * pSCL_Port, uint16_t uSCL_Pin, GPIO_TypeDef * pSDA_Port, uint16_t uSDA_Pin
 5 * Output         : None
 6 * Return         : None
 7 ********************************************************************************/
 8 void vSen_DS3231_Init(IIC_HandleTypedef * iicHandle, DS3231_HandleTypeDef * hDS3231, GPIO_TypeDef * pSCL_Port, uint16_t uSCL_Pin, GPIO_TypeDef * pSDA_Port, uint16_t uSDA_Pin)
 9 {
10   
11   vIIC_Handle_Init(iicHandle, pSCL_Port, uSCL_Pin, pSDA_Port, uSDA_Pin);        //初始化IIC協(xié)議句柄
12   
13   
14 // 年份 月份 日期 星期 時(shí)鐘 分鐘 秒鐘 15 vSen_DS3231_Modify_Time(iicHandle, 19, 5, 10, 5, 21, 45, 00); //DS3231初始化時(shí)間 16 17 }

4.5 成果展示

  因?yàn)槲疫@里用的是數(shù)碼管顯示,但數(shù)碼管格數(shù)不夠,就只顯示了時(shí)分秒三個(gè)數(shù)值。

5. 結(jié)尾

  DS3231模塊已經(jīng)成功驅(qū)動(dòng)了,畢竟這個(gè)模塊是比較容易的一個(gè)IIC傳感,基本不用配置什么寄存器,直接寫(xiě)入再直接讀取即可,算是一個(gè)IIC小入門難度,不過(guò)其他傳感也大同小異,都非常類似。

  對(duì)STM8的I2C傳感模塊驅(qū)動(dòng)講解到這里結(jié)束,感謝各位看官的點(diǎn)擊。

  如果覺(jué)得有所收獲請(qǐng)點(diǎn)下推薦,若認(rèn)為該博客中存在錯(cuò)誤的說(shuō)明或者對(duì)博客中某方面有疑問(wèn)請(qǐng)留言。

作 者:浩宇99✌
出 處:https://www.cnblogs.com/zhenghaoyu/p/10841542.html
版權(quán)聲明:本文原創(chuàng)發(fā)表于 博客園,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則視為侵權(quán)。

總結(jié)

以上是生活随笔為你收集整理的基于STM8的IIC协议--实例篇--时钟模块(DS3231)读取的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。