本文主要介紹如何在QCC300x上實現I2C功能,只在空白工程上實現相關功能。所用的ADK版本為ADK_QCC300x.WIN.1.0.167。
此方法理論上同樣適用于CSR8670/CSR8675。
本文實現的功能很簡單,通過對IIC設備發起一個讀寫操作,從設備有ACK即可。因為如果實現了這個基本操作,后續的其他復雜操作就是怎么寫代碼的問題了。
從寄存器0x06和0x07中讀取:
這里先講一下硬件,本次測試用的是官方的開發板,在開發板的P00和P01口上掛了一顆IC--TCA9555,它是一顆IO擴展芯片,IIC接口,所以,本次測試正好使用這顆芯片作為測試。
QCC300x的IIC默認配置為P00和P01,當然它也可以改成其他IO:
首先,建立一個空白工程,然后工程屬性中有個地方需要改一下:
改Transport的原因是因為我們使用P00和P01作為I2C的接口,如果使用其他IO口,這個應該就不用改了。
然后,我們先燒錄一下程序,這樣它會擦除FLASH并對FLASH進行分區,然后再用pstool merge一下默認的psr程序(這個請參考之前文檔)。然后用pstool改以下配置:
將I2C configuration改為“1”的目的是將IIC的速率切換到400kHz。
下面兩個參數是配置I2C接口所對應的IO口的:
這些配置完畢后,保存pskey,然后,開始編寫我們的代碼。
代碼也很簡單,就一個main.c文檔,代碼內容如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MESSAGE_TX_DATA 0x4000
#define MESSAGE_RX_DATA 0x4001
#define I2C_DEVICE_ADDRESS (0x20<<1)
#define I2C_A_DEVICE_REGISTER 0x06
typedef struct
{
TaskData task;
}I2CTaskData;
I2CTaskData theI2CTaskData;
uint16 i2c_register_data;
static void I2CMessageHandler(Task pTask, MessageId pId,Message pMessage);
static void i2c_example_init(void);
static void i2c_write_16bit_device_register(uint8device_address, uint8 device_register, uint16 data);
static void i2c_read_16bit_device_register(uint8device_address, uint8 device_register, uint16 *data);
int main(void)
{
PRINT(("hello world. "));
i2c_example_init();
/* Start the message scheduler loop */
MessageLoop();
/* Never get here...*/
return 0;
}
void i2c_example_init(void)
{
/* Assign task message handler */
theI2CTaskData.task.handler = I2CMessageHandler;
/* Send MESSAGE_TX_DATA to the task */
MessageSendLater(&theI2CTaskData.task,MESSAGE_TX_DATA, 0, 2000);
/* Send MESSAGE_RX_DATA to the task */
MessageSendLater(&theI2CTaskData.task,MESSAGE_RX_DATA, 0, 1000);
}
void i2c_write_16bit_device_register(uint8device_address, uint8 device_register, uint16 data)
{
uint8 i2c_data[3];
i2c_data[0] = device_register;
i2c_data[1] = (data >> 8) & 0xFF;
i2c_data[2] = data & 0xFF;
/*
I2cTransfer(uint16 address, const uint8 *tx, uint16tx_len, uint8 *rx, uint16 rx_len)
If tx_len is non-zero and rx_len is zero then the sequencereduces to:
- Start condition (S).
- Write slave address and direction byte (address | 0).
- Write tx_len data bytes from the buffer at tx.
- Stop condition (P).
*/
/*I2cTransfer(device_address, i2c_data, 3, NULL, 0);*/
PanicZero(I2cTransfer(device_address, i2c_data, 3, NULL,0));
}
void i2c_read_16bit_device_register(uint8 device_address,uint8 device_register, uint16 *data)
{
uint8 i2c_data[1];
uint8 i2c_rx_data[2];
i2c_data[0] = device_register;
/*
I2cTransfer(uint16 address, const uint8 *tx, uint16tx_len, uint8 *rx, uint16 rx_len)
If tx_len is non-zero and rx_len is non-zero then thesequence is:
- Start condition (S).
- Write slave address and direction byte (address | 0).
- Write tx_len data bytes from the buffer at tx.
- Repeated start condition (Sr).
- Write slave address and direction byte (address | 1).
- Read rx_len bytes into the buffer at rx, acknowledgingall but the final byte.
- Stop condition (P).
*/
/*I2cTransfer(device_address, i2c_data, 1, i2c_rx_data,2);*/
PanicZero(I2cTransfer(device_address, i2c_data, 1,i2c_rx_data, 2));
*data = (i2c_rx_data[0] << 8) + i2c_rx_data[1];
}
void I2CMessageHandler(Task pTask, MessageId pId, MessagepMessage)
{
switch (pId)
{
case MESSAGE_TX_DATA:
/*將數據0x1234寫入到寄存器0x06和0x07中*/
i2c_write_16bit_device_register(I2C_DEVICE_ADDRESS,I2C_A_DEVICE_REGISTER,0x1234);
/* Send MESSAGE_TX_DATA to the task */
MessageSendLater(&theI2CTaskData.task,MESSAGE_TX_DATA, 0, 1000);
break;
case MESSAGE_RX_DATA:
/*從寄存器0x06和0x07中讀取之前寫入的值*/
i2c_read_16bit_device_register(I2C_DEVICE_ADDRESS,I2C_A_DEVICE_REGISTER,&i2c_register_data);
/* Send MESSAGE_RX_DATA to the task */
MessageSendLater(&theI2CTaskData.task,MESSAGE_RX_DATA, 0, 2000);
break;
default:
break;
}
}
也沒啥好講的,直接貼到main.c中,做過嵌入式開發的人,幾分鐘內就能完全讀懂了。跟I2C相關的其實就一個函數:
uint16 I2cTransfer(uint16 address, constuint8 *tx, uint16 tx_len, uint8 *rx, uint16 rx_len);
關于它的解釋,可以參考API的說明。
這里再簡單講一下如何用I2cTransfer實現IIC的最基本的兩個操作吧。
1.寫:
I2cTransfer(device_address, i2c_data, 3, NULL, 0);
以上函數會往device_address的設備將i2c_data數組中的3個字節寫入到iic外設中,i2c_data[0]為device_register,然后后面兩個字節為數據內容:
i2c_data[0]= device_register;
i2c_data[1]= (data >> 8) & 0xFF;
i2c_data[2] = data & 0xFF;
2.讀:
i2c_data[0]= device_register;
I2cTransfer(device_address,i2c_data, 1, i2c_rx_data, 2);
*data = (i2c_rx_data[0] << 8) + i2c_rx_data[1];
以上代碼是從device_register位置讀取兩個字節的標準操作。
更多操作的話,可以參考前面提到的API說明。
最后,編譯運行,就能得到文章一開始的結果了。
責任編輯:YYX
-
寄存器
+關注
關注
31文章
5369瀏覽量
121275 -
IIC
+關注
關注
11文章
302瀏覽量
38537 -
I2C
+關注
關注
28文章
1495瀏覽量
124705
原文標題:【BAQ026A】QCC300x如何實現I2C通信
文章出處:【微信號:TalkBT,微信公眾號:藍牙】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
MM32F013x上實現I2C多地址的功能應用
高通QCC300x系列藍牙芯片應用常見問題的解達
用Verilog HDL實現I2C總線功能
用Verilog HDL實現I2C總線功能
![用Verilog HDL<b class='flag-5'>實現</b><b class='flag-5'>I2C</b>總線<b class='flag-5'>功能</b>](https://file1.elecfans.com//web2/M00/A5/0A/wKgZomUMNqqAU-xkAAAZxRnT5bM160.gif)
啟動belasigna 300使用I2C接口的方法
I2C上拉電阻設計
![<b class='flag-5'>I2C</b><b class='flag-5'>上</b>拉電阻設計](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
如何在Arduino中使用20x4 I2C字符LCD顯示器
![如<b class='flag-5'>何在</b>Arduino中使用20<b class='flag-5'>x</b>4 <b class='flag-5'>I2C</b>字符LCD顯示器](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
如何在顯示器設計中使用TPS6598x I2C控制TUSB564
![如<b class='flag-5'>何在</b>顯示器設計中使用TPS6598<b class='flag-5'>x</b> <b class='flag-5'>I2C</b>控制TUSB564](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論