当前位置:网站首页>IMX6ULL裸機開發之硬件IIC分析及配置過程
IMX6ULL裸機開發之硬件IIC分析及配置過程
2022-04-23 00:54:00 【Swiler】
裸機配置硬件I2C
關於I2C的具體介紹,可以參考我的另一篇文章
IMX6U的硬件I2C特性
- 兼容標准I2C總線;
- 軟件可配置64個不同的串行時鐘頻率;
- 軟件可選的應答信號;
- start/end信號生成和檢測;
- 重複start信號生成;
- 確認比特生成;
- 總線busy檢測。
I2C的兩種模式
- 標准模式:在該模式下I2C傳輸速率可達100kb/s;
- 高速模式:在該模式下I2C傳輸速率可達400kb/s;
外部引脚MAP
IMX6U有4組IIC,這裏舉個例子,另外的參考《IMX6U參考手册》P1244

時鐘
IIC的時鐘源有兩個:
(一個用於讀寫操作的模塊時鐘,一個是I2C的功能時鐘。串行比特時鐘頻率來自於模塊時鐘。模塊時鐘和外圍時鐘相互同步。模塊時鐘的最小頻率應為12.8MHz,以達到400kbps的操作。)

硬件I2C概述圖
從上到下由地址/數據塊,5個寄存器,時鐘塊組成。這樣的block,IMX6U有四個。

寄存器介紹
每組IIC對應5個寄存器,下圖是IIC1的寄存器組

I2Cx_IFDR寄存器
該寄存器用於配置IIC的時鐘,但是不能够隨意配置的,而是有固定的值。該寄存器只有低6比特有效。

I2Cx_I2CR寄存器

IEN:I2C 使能比特,1使能,0關閉
IIEN:I2C 中斷使能比特,1使能,0關閉
MSTA:主從模式選擇比特,1主模式,0從模式
MTX:傳輸方向選擇比特,1接收,0發送
TXAK:傳輸應答比特使能,1發送無應答信號NACK,0發送應答信號ACK
RSTA:重複開始信號,1發送一個restart信號
I2Cx_I2SR寄存器

ICF:數據傳輸狀態比特,0傳輸完成,1正在傳輸
IAAS:為1則錶示IIC地址
IBB:總線BUSY比特,0空閑,1忙
IAL:仲裁丟失比特,為1則發生仲裁丟失
SRW:從機讀寫狀態比特(IIC做從機時使用)
IIF:中斷掛起標志比特,要軟件清零。
RXAK:應答信號標志比特
代碼分析
IIC初始化
void i2c_io_init(void)
{
//配置I2C1的相關引脚
IOMUXC_SetPinMux(IOMUXC_UART4_TX_DATA_I2C1_SCL, 1);
IOMUXC_SetPinMux(IOMUXC_UART4_RX_DATA_I2C1_SDA, 1);
IOMUXC_SetPinConfig(IOMUXC_UART4_TX_DATA_I2C1_SCL, 0x70B0);
IOMUXC_SetPinConfig(IOMUXC_UART4_RX_DATA_I2C1_SDA, 0X70B0);
}
void i2c_init(I2C_Type *base)
{
base->I2CR &= ~(1 << 7); /* 要訪問I2C的寄存器,首先需要先關閉I2C */
base->IFDR = 0X15 << 0; /* 配置分頻系數,以設置I2C波特率為100K */
base->I2CR |= (1<<7); /* 使能IIC設備 */
}
配置IIC的start信號
unsigned char i2c_start(I2C_Type *base, unsigned char address, enum i2c_direction direction)
{
if(base->I2SR & (1 << 5)) /* 檢測I2C是否忙 */
return 1;
base->I2CR |= (1 << 5) | (1 << 4); /* 配置IIC為主模式,數據傳輸方向為發送數據 */
/* 設置從機地址 */
base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
return 0;
}
配置IIC的restart信號
unsigned char i2c_repeated_start(I2C_Type *base, unsigned char address, enum i2c_direction direction)
{
base->I2CR |= (1 << 4) | (1 << 2); /* 配置IIC為發數據方向並產生一個restart信號 */
/* 設置從機地址 */
base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
return 0;
}
配置IIC的停止信號
unsigned char i2c_master_stop(I2C_Type *base)
{
unsigned short timeout = 0xffff;
/* 清除I2CR的bit[5:3]這三比特 */
base->I2CR &= ~((1 << 5) | (1 << 4) | (1 << 3));
/* 等待忙結束(超時等待) */
while((base->I2SR & (1 << 5)))
{
timeout--;
if(timeout == 0) /* 超時跳出 */
return I2C_STATUS_TIMEOUT;
}
return I2C_STATUS_OK;
}
配置發送和接收函數
void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size)
{
/* 等待傳輸完成 */
while(!(base->I2SR & (1 << 7)));
base->I2SR &= ~(1 << 1); /* 清除標志比特 */
base->I2CR |= 1 << 4; /* 發送數據 */
while(size--)
{
base->I2DR = *buf++; /* 將buf中的數據寫入到I2DR寄存器 */
while(!(base->I2SR & (1 << 1))); /* 等待傳輸完成 */
base->I2SR &= ~(1 << 1); /* 清除標志比特 */
if(i2c_check_and_clear_error(base, base->I2SR)) /* 檢查有無ACK */
break;
}
base->I2SR &= ~(1 << 1);
i2c_master_stop(base); /* 發送停止信號 */
}
void i2c_master_read(I2C_Type *base, unsigned char *buf, unsigned int size)
{
volatile uint8_t dummy = 0;
dummy++; /* 防止編譯報錯 */
while(!(base->I2SR & (1 << 7))); /* 等待傳輸完成 */
base->I2SR &= ~(1 << 1); /* 清除中斷掛起比特 */
base->I2CR &= ~((1 << 4) | (1 << 3)); /* 接收數據 */
if(size == 1) /* 如果只接收一個字節數據的話發送NACK信號 */
base->I2CR |= (1 << 3);
dummy = base->I2DR; /* 假讀 */
while(size--) /* 直到數據發送完為止 */
{
while(!(base->I2SR & (1 << 1))); /* 等待傳輸完成 */
base->I2SR &= ~(1 << 1); /* 清除標志比特 */
if(size == 0)
{
i2c_master_stop(base); /* 發送停止信號 */
}
if(size == 1)
{
base->I2CR |= (1 << 3);
}
*buf++ = base->I2DR;
}
}
- 有了以上的幾個函數,所有的IIC傳輸數據的模塊就集齊了,接下來就是將這些模塊組裝在一起,構成IIC的傳輸函數。
傳輸函數
unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer)
{
unsigned char ret = 0;
enum i2c_direction direction = xfer->direction;
base->I2SR &= ~((1 << 1) | (1 << 4)); /* 清除標志比特 */
/* 等待傳輸完成 */
while(!((base->I2SR >> 7) & 0X1)){
};
/* 如果是讀的話,要先發送寄存器地址,所以要先將方向改為寫 */
if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read))
{
direction = kI2C_Write;
}
ret = i2c_master_start(base, xfer->slaveAddress, direction); /* 發送開始信號 */
if(ret)
{
return ret;
}
while(!(base->I2SR & (1 << 1))){
}; /* 等待傳輸完成 */
ret = i2c_check_and_clear_error(base, base->I2SR); /* 檢查是否出現傳輸錯誤 */
if(ret)
{
i2c_master_stop(base); /* 發送出錯,發送停止信號 */
return ret;
}
/* 發送寄存器地址 */
if(xfer->subaddressSize)
{
do
{
base->I2SR &= ~(1 << 1); /* 清除標志比特 */
xfer->subaddressSize--; /* 地址長度减一 */
//向I2DR寄存器寫入子地址
base->I2DR = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
while(!(base->I2SR & (1 << 1))); /* 等待傳輸完成 */
/* 檢查是否有錯誤發生 */
ret = i2c_check_and_clear_error(base, base->I2SR);
if(ret)
{
i2c_master_stop(base); /* 發送停止信號 */
return ret;
}
}
while ((xfer->subaddressSize > 0) && (ret == I2C_STATUS_OK));
if(xfer->direction == kI2C_Read) /* 讀取數據 */
{
base->I2SR &= ~(1 << 1); /* 清除中斷掛起比特 */
/* 發送重複開始信號和從機地址 */
i2c_master_repeated_start(base, xfer->slaveAddress, kI2C_Read);
while(!(base->I2SR & (1 << 1))){
};/* 等待傳輸完成 */
/* 檢查是否有錯誤發生 */
ret = i2c_check_and_clear_error(base, base->I2SR);
if(ret)
{
ret = I2C_STATUS_ADDRNAK;
i2c_master_stop(base); /* 發送停止信號 */
return ret;
}
}
}
/* 發送數據 */
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
{
i2c_master_write(base, xfer->data, xfer->dataSize);
}
/* 讀取數據 */
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
{
i2c_master_read(base, xfer->data, xfer->dataSize);
}
return 0;
}
頭文件
#include "imx6ul.h"
/* 相關宏定義 */
#define I2C_STATUS_OK (0)
#define I2C_STATUS_BUSY (1)
#define I2C_STATUS_IDLE (2)
#define I2C_STATUS_NAK (3)
#define I2C_STATUS_ARBITRATIONLOST (4)
#define I2C_STATUS_TIMEOUT (5)
#define I2C_STATUS_ADDRNAK (6)
/* * I2C方向枚舉類型 */
enum i2c_direction
{
kI2C_Write = 0x0, /* 主機向從機寫數據 */
kI2C_Read = 0x1, /* 主機從從機讀數據 */
} ;
/* * 主機傳輸結構體 */
struct i2c_transfer
{
unsigned char slaveAddress; /* 7比特從機地址 */
enum i2c_direction direction; /* 傳輸方向 */
unsigned int subaddress; /* 寄存器地址 */
unsigned char subaddressSize; /* 寄存器地址長度 */
unsigned char *volatile data; /* 數據緩沖區 */
volatile unsigned int dataSize; /* 數據緩沖區長度 */
};
/* *函數聲明 */
void i2c_init(I2C_Type *base);
unsigned char i2c_master_start(I2C_Type *base, unsigned char address, enum i2c_direction direction);
unsigned char i2c_master_repeated_start(I2C_Type *base, unsigned char address, enum i2c_direction direction);
unsigned char i2c_check_and_clear_error(I2C_Type *base, unsigned int status);
unsigned char i2c_master_stop(I2C_Type *base);
void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size);
void i2c_master_read(I2C_Type *base, unsigned char *buf, unsigned int size);
unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer);
#endif
版权声明
本文为[Swiler]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230053490481.html
边栏推荐
- 智能照明控制系统在医院的设计与应用
- tdengine集群安装部署
- L2-013 red alarm (25 points)
- 换个姿势看 hooks,灵感来源组合和 HOC 模式下逻辑视图分离新创意
- be based on. NETCORE development blog project starblog - (2) environment preparation and creation project
- L2-002 linked list weight removal (25 points)
- Multi surveyor Xiao sir, Gongshu campus, Hangzhou_ Senior gold medal lecturer_ Resume practice
- What is the lifecycle of automated testing?
- Kubeflow create new user password
- 安全用电管理平台在靖边博物馆安全用电管理系统的应用
猜你喜欢

Deep learning basic learning - RNN and ltsm

Amazon Aurora's ability to read and write: shardingsphere proxy

2.58 - write the program is little endian, which returns 1 when compiled and run on the small end method machine and 0 when compiled and run on the large end method machine. This program should be abl

Alibaba cloud container & Service Grid product technology trends (202203)

How to become a real digital enterprise? Ruijie network releases the digital force awakening plan

C WPF UI framework mahapps switching theme

Lightly: a new generation of cloud IDE

员工公寓楼建设项目电力监控系统的研究与应用

Essay 8: error in readpng (paste (location, "/", pattern. Type [i], ". PNG", Sep = "): unable to open C:/

Acrel-2000型电力监控系统在兴庆坊新兴广场配电所配电回路用电的实时监控和管理
随机推荐
leetcode 396. 旋转函数
多测师肖sir_高级金牌讲师_面试题
Frequently asked questions about recent BSN development
Cross domain problem and solving cross domain problem by UMI proxy proxy
Deloitte 2022 technology trend: it self subversion, technology cross-border integration and innovation
jsp 转换为thymeleaf格式的部分方式
Flash project cross domain interception and DBM database learning [Baotou cultural and creative website development]
openresty安装与入门
BUUCTF 隐藏的钥匙
What is the lifecycle of automated testing?
安全用电管理平台在靖边博物馆安全用电管理系统的应用
Change your posture to look at hooks, the combination of inspiration sources and the separation of new ideas from logical view in hoc mode
Xamarin effect Chapter 22 recording effect
Deep learning basic learning - RNN and ltsm
Multi surveyor Xiao sir, Gongshu campus, Hangzhou_ Senior gold medal lecturer_ Resume making explanation
Acrel-2000型电力监控系统在兴庆坊新兴广场配电所配电回路用电的实时监控和管理
Acrel-3200远程预付费电能管理系统 在福州万宝产业园的应用
智能无线传输模组,CV5200助力无人机mesh组网,无线通信传输方案
Source code analysis of synchronousqueue
From construction to governance, the industry's first white paper on microservice governance technology was officially released (including a free download link)