STM32Cube MX 下IIC的配置與使用--GPIO模擬
本文介紹了在STM32下的IIC的基本使用方法,通過對板載具備IIC介面EEPROM的讀寫,完成對IIC驅動程式的測試。
硬體平臺:STM32F107VCT6開發板
軟體平臺:STM32Cube MX + MDK5.22
1. 進行STM32Cube MX的配置
配置PB6和PB7為輸出模式,同時配置了USART1進行串列埠除錯使用。然後生成工程。
2. 開啟工程,可以看到GPIO的初始化狀態
3. 模擬IIC驅動程式原始檔程式碼
/** * @file iic_dup.c * @brief IIC上層程式 * @par date version author remarks * 2016-03-21 v1.0 zbt 初次建立 * */ /** 標頭檔案包含區 ------------------------------------------------ */ #include "iic_dup.h" /** 私有巨集(型別定義) -------------------------------------------- */ #define IIC1_SCL(pin_status) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, pin_status); #define IIC1_SDA(pin_status) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, pin_status); #define IIC1_SCL_IS_HIGH() (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) != GPIO_PIN_RESET) #define IIC1_SDA_IS_HIGH() (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) != GPIO_PIN_RESET) /** 私有變數 --------------------------------------------------- */ /** 外部變數 --------------------------------------------------- */ /** 私有函式原型 ----------------------------------------------- */ static void iic_delay(void); /** 公有函式 --------------------------------------------------- */ /** * @brief IIC啟動 * @param None * @retval None * @note 當SCL處於高電平狀態時,SDA出現一個下降沿 即產生IIC啟動訊號 */ void iic_start(void) { IIC1_SCL(GPIO_PIN_SET); /** SDA產生一個下降沿 */ IIC1_SDA(GPIO_PIN_SET); iic_delay(); IIC1_SDA(GPIO_PIN_RESET); iic_delay(); IIC1_SCL(GPIO_PIN_RESET); /**< 拉低準備傳送資料 */ iic_delay(); } /** * @brief IIC停止 * @param None * @retval None * @note 當SCL處於高電平狀態時,SDA出現一個上升沿 即產生IIC停止訊號 */ void iic_stop(void) { IIC1_SCL(GPIO_PIN_RESET); iic_delay(); /** SDA產生一個上升沿 */ IIC1_SDA(GPIO_PIN_RESET); iic_delay(); IIC1_SCL(GPIO_PIN_SET); iic_delay(); IIC1_SDA(GPIO_PIN_SET); iic_delay(); } /** * @brief IIC傳送1byte資料 * @param None * @retval None * @note */ void iic_sendbyte(uint8_t byte) { uint8_t i; /** 傳送一個位元組的高7位 */ for (i = 0; i < 8; i++) { if (byte & 0x80) { IIC1_SDA(GPIO_PIN_SET); } else { IIC1_SDA(GPIO_PIN_RESET); } iic_delay(); IIC1_SCL(GPIO_PIN_SET); iic_delay(); IIC1_SCL(GPIO_PIN_RESET); if (i == 7) { IIC1_SDA(GPIO_PIN_SET); } byte <<= 1; iic_delay(); } } /** * @brief IIC讀取1byte資料 * @param None * @retval None * @note */ uint8_t iic_readbyte(void) { uint8_t i; uint8_t recv_value = 0; IIC1_SDA(GPIO_PIN_SET); iic_delay(); for (i = 0; i < 8; i++) { IIC1_SCL(GPIO_PIN_SET); iic_delay(); recv_value <<= 1; if (IIC1_SDA_IS_HIGH()) { recv_value |= 0x01; } else { recv_value &= ~0x01; } iic_delay(); IIC1_SCL(GPIO_PIN_RESET); } return recv_value; } /** * @brief IIC等待應答訊號 * @param None * @retval ack_status: 應答狀態,0表示應答,1表示裝置無響應 */ uint8_t iic_wait_ack(void) { uint8_t ack_status = 0; /** 在等待應答訊號之前,要釋放匯流排,即將SDA置位 */ IIC1_SDA(GPIO_PIN_SET); iic_delay(); IIC1_SCL(GPIO_PIN_SET); iic_delay(); if (IIC1_SDA_IS_HIGH()) { ack_status = 1; iic_stop(); } else { ack_status = 0; } IIC1_SCL(GPIO_PIN_RESET); iic_delay(); return ack_status; } /** * @brief 主機(主控制器)產生應答訊號 * @param None * @retval None */ void iic_ack(void) { IIC1_SDA(GPIO_PIN_RESET); iic_delay(); IIC1_SCL(GPIO_PIN_SET); iic_delay(); IIC1_SCL(GPIO_PIN_RESET); iic_delay(); IIC1_SDA(GPIO_PIN_SET); } /** * @brief 主機(主控制器)產生不應答訊號 * @param None * @retval None */ void iic_nack(void) { IIC1_SDA(GPIO_PIN_SET); iic_delay(); IIC1_SCL(GPIO_PIN_SET); iic_delay(); IIC1_SCL(GPIO_PIN_RESET); iic_delay(); } /** * @brief 檢測IIC總線上的裝置狀態 * @param device_addr: 從機裝置地址 * @retval ack_status: 0 (正常)or 1(異常) * @note 主機發送裝置地址等待從機應答,若有從機正確的應答訊號 則表明IIC總線上掛接了裝置,否則表示IIC總線上未檢測到 裝置 */ uint8_t iic_check_device_status(uint8_t device_addr) { uint8_t ack_status; if (IIC1_SCL_IS_HIGH() && IIC1_SDA_IS_HIGH()) { iic_start(); iic_sendbyte(device_addr | IIC_WRITE); ack_status = iic_wait_ack(); iic_stop(); return ack_status; } return 1; } /** 私有函式 --------------------------------------------------- */ /** * @brief 用於模擬IIC時的簡單延時 * @param None * @retval None */ static void iic_delay(void) { uint8_t i = 0; uint8_t delay = 5; while (delay--) { i = 10; while (i--); } }
4. AT24C02部分驅動程式碼
/** * @file at24c02.c * @brief at24c02驅動程式 * @par date version author remarks * 2016-03-21 v1.0 zbt 初次建立 * */ /** 標頭檔案包含區 ------------------------------------------------ */ #include "at24c02.h" #include "iic_dup.h" /** 私有巨集(型別定義) -------------------------------------------- */ #define AT24C02_DEVICE_ADDR 0xA0 #define AT24C02_PAGE_SIZE 8 #define AT24C02_MEM_SIZE 256 #define AT24C02_ADDR_BYTE 1 /** 私有變數 --------------------------------------------------- */ uint8_t test_buffer[AT24C02_MEM_SIZE]; /** 外部變數 --------------------------------------------------- */ /** 私有函式原型 ----------------------------------------------- */ //static void AT24C02_ack(void); static void AT24C02_error_handle(void); static void AT24C02_read_test(void); static void AT24C02_write_test(void); static void AT24C02_erase_test(void); /** 公有函式 --------------------------------------------------- */ /** * @brief AT24C02與主控制器的IIC通訊測試程式碼 * @param None * @retval None */ void AT24C02_iic_test(void) { iic_stop(); /**< 必須先復位IIC總線上的裝置到待機模式 */ HAL_Delay(10); /** 檢測總線上是否掛接了IIC裝置(此處為AT24C02) */ if (iic_check_device_status(AT24C02_DEVICE_ADDR) == 0) { printf("iic device exists\n"); } else { printf("no iic device exists\n"); } AT24C02_write_test(); HAL_Delay(5); AT24C02_read_test(); HAL_Delay(5); AT24C02_erase_test(); } /** * @brief 從AT24C02中讀取資料 * @param read_data: 讀取到的資料 * @param start_addr: 讀取資料的起始地址 * @param data_length: 資料的長度 * @retval None */ void AT24C02_read_data(uint8_t *read_data, uint16_t start_addr, uint16_t data_length) { uint16_t i; iic_start(); iic_sendbyte(AT24C02_DEVICE_ADDR | IIC_WRITE); // AT24C02_ack(); if (iic_wait_ack() != 0) { AT24C02_error_handle(); printf("first read error\r\n"); } if (AT24C02_ADDR_BYTE == 1) { iic_sendbyte((uint8_t)start_addr & 0xff); // AT24C02_ack(); if (iic_wait_ack() != 0) { AT24C02_error_handle(); printf("addr byte error\r\n"); } } iic_start(); iic_sendbyte(AT24C02_DEVICE_ADDR | IIC_READ); // AT24C02_ack(); if (iic_wait_ack() != 0) { AT24C02_error_handle(); printf("read data error\r\n"); } for (i = 0; i < data_length; i++) { read_data[i] = iic_readbyte(); if (i != data_length - 1) { iic_ack(); /**< 讀完非最後一個位元組後, 產生應答訊號 */ } else { iic_nack(); /**< 最後一個位元組讀完後 產生非應答訊號 */ } // printf("read data is %d\n", read_data[i]); /**< 除錯程式碼 */ } iic_stop(); } /** * @brief 通過IIC向AT24C02寫資料 * @param write_data: 要寫入AT24C02的資料指標 * @param start_addr: 要寫入AT24C02的起始地址 * @param data_length: 要寫入AT24C02的資料長度 * @retval None */ void AT24C02_write_data(uint8_t *write_data, uint16_t start_addr, uint16_t data_length) { uint16_t i, j; uint16_t start_addr_dup; start_addr_dup = start_addr; for (i = 0; i < data_length; i++) { if ((i == 0) || (start_addr_dup & (AT24C02_PAGE_SIZE - 1)) == 0) { iic_stop(); for (j = 0; j < 2000; j++) { iic_start(); iic_sendbyte(AT24C02_DEVICE_ADDR | IIC_WRITE); if (iic_wait_ack() == 0) { break; } } if (j >= 2000) { printf("j = 1000\r\n"); AT24C02_error_handle(); } if (AT24C02_ADDR_BYTE == 1) { iic_sendbyte((uint8_t)start_addr_dup & 0xff); // AT24C02_ack(); if (iic_wait_ack() != 0) { AT24C02_error_handle(); printf("addr_byte wrong\r\n"); } } } iic_sendbyte(write_data[i]); // AT24C02_ack(); if (iic_wait_ack() != 0) { AT24C02_error_handle(); printf("write failed\r\n"); } // printf("write_data is %d \n", write_data[i]); /**< 除錯程式碼 */ start_addr_dup++; } iic_stop(); } /** 私有函式 --------------------------------------------------- */ /** 以下為測試用程式 ------------------------------------------- */ /** * @brief AT24C02讀取資料測試 * @param None * @retval None */ static void AT24C02_read_test(void) { uint16_t i; AT24C02_read_data(test_buffer, 0, (AT24C02_MEM_SIZE % 10)); printf("read data is:\n"); for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++) { printf("%d ", test_buffer[i]); } printf("\r\nread test ok\r\n"); } /** * @brief AT24C02寫資料測試 * @param None * @retval None */ static void AT24C02_write_test(void) { uint16_t i; for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++) { test_buffer[i] = i; } AT24C02_write_data(test_buffer, 0, (AT24C02_MEM_SIZE % 10)); printf("write data is:\n"); for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++) { printf("%d ", test_buffer[i]); } printf("\r\nwrite test ok\r\n"); } /** * @brief AT24C02擦除資料測試 * @param None * @retval None */ static void AT24C02_erase_test(void) { uint16_t i; for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++) { test_buffer[i] = 0xff; } AT24C02_write_data(test_buffer, 0, (AT24C02_MEM_SIZE % 10)); printf("erase value is: \n"); for (i = 0; i < (AT24C02_MEM_SIZE % 10); i++) { printf("%d ", test_buffer[i]); } printf("\r\nerase test ok\r\n"); } /** 以上為測試用程式 ------------------------------------------- */ /** * @brief AT24C02應答錯誤處理程式 * @param None * @retval None */ static void AT24C02_error_handle(void) { iic_stop(); // printf("At24C02 read failed\r\n"); /**< 除錯用 */ } //static void AT24C02_ack(void) //{ // if (iic_wait_ack() != 0) // { // AT24C02_error_handle(); // } //}
5. 在主函式中新增 AT24C02_iic_test(); 進行讀寫測試成功。
相關推薦
STM32Cube MX 下IIC的配置與使用--GPIO模擬
本文介紹了在STM32下的IIC的基本使用方法,通過對板載具備IIC介面EEPROM的讀寫,完成對IIC驅動程式的測試。 硬體平臺:STM32F107VCT6開發板 軟體平臺:STM32Cube MX + MDK5.22 1. 進行STM32Cube MX的配置 配置P
win7 下 jenkins 配置與使用
錯誤 新版 一個 pan 其中 line 用戶註冊 安裝路徑 輸出 一、Jenkins的配置 1. 下載地址: Jenkins的官方網站:http://jenkins-ci.org/ 目前最新版本的Windows版:https://jenkins.io/download/t
apache下https配置與優化效能具體操作
宣告:以下操作路徑及 httpd.conf檔案與原始檔案有所區別,博主採用的httpd.conf引入其他配置檔案進行分專案管理,大體操作類似 對於nginx參考騰訊實踐-騰訊HTTPS效能優化實踐 *可以忽略此段 -http.txt 檔案為80埠配置檔案修改後綴為conf,重啟apa
ubuntu16.04下vim配置與自動補全
開啟終端,輸入vim ~/.vimrc 將以下內容儲存 set nocompatible "去掉有關vim一致性模式,避免以前版本的一些bug和侷限. set mouse=a "滑鼠可任意移動 set number "顯示行號. set ruler "顯示當
Opencv 2.4.9在Ubuntu下的配置與安裝
一、依賴包安裝 1. build-essential 軟體包,為編譯程式提供必需軟體包的列表資訊,這樣軟體包才知道標頭檔案、庫函式在哪裡。還會下載依賴的軟體包,安裝gcc/g++/gdb/make 等基本程式設計工具,最後才組成一個開發環境。 sudo a
【Docker】Docker學習筆記(1)-Windows下的配置與安裝
第一次接觸Docker是15年夏天,那時候在七牛學習Go語言,周圍的大牛們突然提到Docker容器這個東西,而且非常火爆~直到一年多後才想起來要學習一下Docker到底是個什麼東西(我真是怠惰啊),廢話不多說,開始正文。 配置Hyper-V環境並安裝Doc
配置核心gpio模擬spi時序的方法
假如你現在有一份基於核心介面SPI的驅動,但是現在你的硬體已經沒有多餘的SPI介面了。怎麼辦?難道我們需要重新寫驅動嗎,像微控制器一樣去操作IO的高低來符合時序。那麼你的工作量就加大了。其實,linux核心已經寫好了模擬SPI時序,你只需要配置好。就可以使用了。下面分享一下
Linux下NFS配置與tftp配置
1. NFS配置 vi /etc/export 加入所需要共享目錄。例如: /home/liukang/workship 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check) 修改完畢後,執行 #exportfs
Window2003下ss配置與連線
這個,ss是啥? 能搜到這篇文章的同學我就不解釋了 這個網上這方面的教程也很多 最近我搜了一下,發現很多原來的文章都不見了。。。好吧 我對win體系的伺服器配置也沒有多少經驗 寫寫自己實際操作的經驗吧 這個,要想那個啥,你得先有一個 V P S
網絡硬件設備配置與管理(CCNA)下
網絡 硬件 cisco ccna 點擊下載:網絡硬件設備配置與管理(CCNA)下本文出自 “飛奔的魚兒” 博客,請務必保留此出處http://feiyuer.blog.51cto.com/6967044/1931155網絡硬件設備配置與管理(CCNA)下
window下MongoDB的配置與安裝
ets ann sock important sof hot sys support 環境 前言 MongoDB 是一個基於分布式文件存儲的數據庫。由C++語言編寫,支持Windows,Linux,OSX,Solaris等平臺,默認端口為27017,是一個效率非常高的no
linux下LAMP安裝與配置
函數 rri osi ase live ins php expose share 安裝 一. Apache 安裝 yum install -y httpd啟動 /etc/init.d/httpd start備註:Apache啟動之後會提示錯誤: 正在啟動http
Linux下安裝Nginx與配置
目錄 openssl oct pan yum安裝 usr 負載均衡 官方 err 一,安裝GCC yum安裝gcc-c ++ -y 二,安裝nginx的所需要的依賴庫 yum -y安裝zlib-devel openssl-devel pcre-devel
Redis在Linux下的安裝與配置
conf eas etc 下載 127.0.0.1 基於內存 最新 ansi lin Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。 Redis是 NoSQL技術陣營中的一員。 說到
linux下FTP安裝與配置
linux ftp pure-ftpdcd /usr/local/src/wget http://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.42.tar.bz2 (下載pureftp源碼包)tar jxvf pure-f
linux下rsync安裝與配置
linux rsync rsync (同步數據,支持增量備份)使用方法:rsync -av 192.168.31.182:/tmp/1.txt /tmp/ (將服務器192.168.31.182中tmp文件夾下的1.txt文件拷貝到本機的tmp目錄下)rsync -av /tmp/1.tx
VMware下網絡模式配置與IP地址無法正常獲取及解決方案
什麽 應該 任務 互連 但我 intern 資料 for 互聯 目錄一 網絡配置中出現的錯誤及解決方案二 VMware下網絡配置的三種模式簡介 1、橋接模式(Bridged) 2、網絡地址轉化模式(NAT) 3、僅主機模式(host-only)一 網
windows下PostgreSQL 安裝與配置
this 開始 ror scripting ping 存儲 install driver 選擇 下載地址 https://www.postgresql.org/download/ Download the installer certified by Enterpris
centos7下NFS使用與配置
nfs linuxnfs centosnfs NFS是Network File System的縮寫,即網絡文件系統。客戶端通過掛載的方式將NFS服務器端共享的數據目錄掛載到本地目錄下。一、NFS的工作流程1、由程序在NFS客戶端發起存取文件的請求,客戶端本地的RPC(rpcbind)服務會
ubuntu16.04下hive安裝與配置
cep ted dir mave value usr ubunt java HA 下載 wget http://mirrors.hust.edu.cn/apache/hive/hive-2.3.2/apache-hive-2.3.2-bin.tar.gz 解壓到指定