亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

arm9 IIC接口有什么用

發布時間:2021-12-20 10:46:42 來源:億速云 閱讀:109 作者:iii 欄目:互聯網科技

本篇內容主要講解“arm9 IIC接口有什么用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“arm9 IIC接口有什么用”吧!

在2440的使用中其iic接口一般用來讀取外圍芯片的數據, 這種情況下2440處于主機模式, 本例用中斷的方式來講述 主機發送/主機接收 模式.

主機發送模式使用流程:

arm9 IIC接口有什么用

    IICCON: 是否返回ack, 總線時鐘選擇, 中斷標志

arm9 IIC接口有什么用

IICCON[7]  在發送模式該位沒有意義, 因為發送模式下主機只接收ACK信號, 并不主動發出ACK. 

                    在接收模式中當從機返回了數據之后, 如果主機需要從機繼續返回數據就必須發送一個ACK, 否則數據發送方不會繼續發送數據. 

綜上: 無論是主/從, 只要接收數據的一方想要繼續通信就必須要發送一個ACK信號, 所以ACK信號絕對是由接收數據的一方來發出的. 

IICCON[5] 必須為1, 否則IICCON[4]無法使用

IICCON[4] 0: 無中斷發生   1: 有中斷發生, 這時總線傳輸中止. 如果要繼續傳輸則需將該位清0

發生中斷的條件: 1. 總線仲裁失敗   2. 發送/接收完一個字節  3. 當廣播或從地址匹配成功

    GPEUP  |= 0xc000;       // 禁止內部上拉
    GPECON |= 0xa0000000;   // 選擇引腳功能:GPE15:IICSDA, GPE14:IICSCL

    INTMSK &= ~(BIT_IIC);	//清除IIC中斷屏蔽位

    /* bit[7] = 1, 使能ACK
     * bit[6] = 0, IICCLK = PCLK/16
     * bit[5] = 1, 使能中斷
     * bit[3:0] = 0xf, Tx clock = IICCLK/16
     * PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz
     */
    IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);  // 0xaf

    IICSTAT = 0x10;     // IICSTAT[4]:I2C串行輸出使能(Rx/Tx), 這里可以不必配置該寄存器, 因為真正開始發送/接收的時候會重新配置IICSTAT(見下邊的I2C_Write)

IICADD: 當2440作為從機的時候, 本身的iic地址可以由該寄存器來設置. 

IICSTAT :  主從模式選擇,  S/P信號發送, 標記各種狀態

arm9 IIC接口有什么用

IICSTAT[7:6] 主從模式選擇

IICSTAT[5] 讀取此位時 0 : 總線空閑,  1 : 總線忙 ;   寫入0: 發出 P 信號,   寫入 1: 發出 S 信號

IICSTAT[4] 開啟收發

IICSTAT[3] 總線仲裁成功標志位

IICSTAT[2]  當2440作為從機時, 接收到的地址和IICADD匹配則該位置一, 在檢測到 S/P 信號時自動清0

IICSTAT[1] 當接收到 0x00 地址時置一, 當檢測到 S/P 信號時自動清0

IICSTAT[0] 0: 接收到ACK;   1: 沒有接收到ACK

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *以下為中斷方式操作I2C接口的主要代碼, 從機芯片為 m41t11* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

在啟動文件中設定好I2C中斷的異常向量, 在ISR中清除異常標志

//head.S中設置異常向量
@ 0x1c: 快中斷模式的向量地址
HandleFIQ:
    b   HandleFIQ
    
//interrupt.c中的ISR, 該ISR總查詢到了IIC中斷, 調取了IIC異常處理函數
void IRQ_Handle(void)
{
	unsigned long oft = INTOFFSET;

	//清中斷
	if (oft == 4)
        EINTPEND = 1<<7;    //EINT4-7合用IRQ4,注意EINTPEND[3:0]保留未用,向這些位寫入1可能導致未知結果

	SRCPND = 1<<oft;
	INTPND = INTPND;

    /* 調用中斷服務程序 */
    isr_handle_array[oft]();
}

以下為IIC的主要操作:

#define WRDATA      (1)
#define RDDATA      (2)

typedef struct tI2C {
    unsigned char *pData;   /* 數據緩沖區 */
    volatile int DataCount; /* 等待傳輸的數據長度 */
    volatile int Status;    /* 狀態 */
    volatile int Mode;      /* 模式:讀/寫 */
    volatile int Pt;        /* pData中待傳輸數據的位置 */
}tS3C24xx_I2C, *ptS3C24xx_I2C;

static tS3C24xx_I2C g_tS3C24xx_I2C;

// I2C初始化
void i2c_init(void)
{
    GPEUP  |= 0xc000;       // 禁止內部上拉
    GPECON |= 0xa0000000;   // 選擇引腳功能:GPE15:IICSDA, GPE14:IICSCL

    INTMSK &= ~(BIT_IIC);   //允許IIC中斷

    /* bit[7] = 1, 使能ACK
     * bit[6] = 0, IICCLK = PCLK/16
     * bit[5] = 1, 使能中斷
     * bit[3:0] = 0xf, Tx clock = IICCLK/16
     * PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz
     */
    IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);  // 0xaf

    IICADD  = 0x10;     // S3C24xx slave address = [7:1]  這句可以不需要的, 該寄存器只在2440作為從機才有用
    IICSTAT = 0x10;     // I2C串行輸出使能(Rx/Tx)    這句也可以不用, 因為真正寫的時候又重新配置了IICSTAT
}

/*
 * 主機發送
 * slvAddr : 從機地址,buf : 數據存放的緩沖區,len : 數據長度 
 */
void i2c_write(unsigned int slvAddr, unsigned char *buf, int len)
{
    g_tS3C24xx_I2C.Mode = WRDATA;   // 寫操作
    g_tS3C24xx_I2C.Pt   = 0;        // 索引值初始為0
    g_tS3C24xx_I2C.pData = buf;     // 保存緩沖區地址
    g_tS3C24xx_I2C.DataCount = len; // 傳輸長度
    
    IICDS   = slvAddr;
    IICSTAT = 0xf0;         // 主機發送,啟動
    
    /* 等待直至數據傳輸完畢 */    
    while (g_tS3C24xx_I2C.DataCount != -1);
}
        
//  主機接收
//  slvAddr : 從機地址,buf : 數據存放的緩沖區,len : 數據長度 
void i2c_read(unsigned int slvAddr, unsigned char *buf, int len)
{
    g_tS3C24xx_I2C.Mode = RDDATA;   // 讀操作
    g_tS3C24xx_I2C.Pt   = -1;       // 索引值初始化為-1,表示第1個中斷時不接收數據(地址中斷)
    g_tS3C24xx_I2C.pData = buf;     // 保存緩沖區地址
    g_tS3C24xx_I2C.DataCount = len; // 傳輸長度
    
    IICDS        = slvAddr;
    IICSTAT      = 0xb0;    // 主機接收,啟動
    
    /* 等待直至數據傳輸完畢 */    
    while (g_tS3C24xx_I2C.DataCount != -1);
}

//  I2C中斷服務程序
//  根據剩余的數據長度選擇繼續傳輸或者結束
void I2CIntHandle(void)
{
    unsigned int iicSt,i;

    // 清中斷
    SRCPND = BIT_IIC;
    INTPND = BIT_IIC;

    iicSt  = IICSTAT;

    //先判斷是不是仲裁失敗引起的中斷
    if(iicSt & 0x8){ printf("Bus arbitration failed\n\r"); }

    switch (g_tS3C24xx_I2C.Mode)
    {
        case WRDATA:
        {
            //檢測是否數據發送完畢, 若完畢: 發送P信號, 數據長度=-1
            if((g_tS3C24xx_I2C.DataCount--) == 0)
            {
                // 下面兩行用來恢復I2C操作,發出P信號
                IICSTAT = 0xd0;
                IICCON  = 0xaf;
                Delay(10000);  // 等待一段時間以便P信號已經發出
                break;         //注意這里的break, 發送P信號完畢直接返回.
            }
            //若數據未發送完畢直接發送, 緩沖區索引值++
            IICDS = g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++];

            // 將數據寫入IICDS后,需要一段時間才能出現在SDA線上
            for (i = 0; i < 10; i++);

            IICCON = 0xaf;      // 恢復I2C傳輸
            break;
        }

        case RDDATA:
        {
            // 這次中斷是發送I2C設備地址后發生的,沒有數據, 第一次發送完地址之后(發送完一個字節會產生中斷)產生的中斷, 接收數據之后2440是需要發出ACK信號的
            if (g_tS3C24xx_I2C.Pt == -1)
            {
                // 只接收一個數據時,不要發出ACK信號
                g_tS3C24xx_I2C.Pt = 0;//準備從數據緩存區的0開始發送數據
                if(g_tS3C24xx_I2C.DataCount == 1)
                   IICCON = 0x2f;   // 恢復I2C傳輸,開始接收數據,關閉ACK, 接收到數據時不發出ACK, 最后一個數據要先關閉ack, 因為最后一個數據要發送no ack, 其實就是不發送ack
                else
                   IICCON = 0xaf;   // 恢復I2C傳輸,開始接收數據, 0x2f與0xaf的區別就是前者不開ack
                break;
            }

            if ((g_tS3C24xx_I2C.DataCount--) == 0)
            {
            	//如果要讀取的剩余數據長度為0, 就發送P信號
                g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++] = IICDS;

                // 下面兩行恢復I2C操作,發出P信號
                IICSTAT = 0x90;
                IICCON  = 0xaf;
                Delay(10000);  // 等待一段時間以便P信號已經發出
                break;
            }

           g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++] = IICDS;

           // 接收最后一個數據時,不要發出ACK信號
           if(g_tS3C24xx_I2C.DataCount == 0)
               IICCON = 0x2f;   // 恢復I2C傳輸,接收到下一數據時無ACK
           else
               IICCON = 0xaf;   // 恢復I2C傳輸,接收到下一數據時發出ACK
           break;
        }

        default:
            break;
    }
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *以上為中斷方式操作I2C總線, 以下使用輪詢方式來操作* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

以下以 LM75(數字溫度傳感器) 來說明 輪詢方式 讀取溫度值的方法. 

控制過程: 1. 讀取溫度值之前需要先指定 LM75 的寄存器, LM75 的寄存器 0x0 是溫度寄存器器(READ ONLY).  所以先發送S信號再發送 LM75 的地址, 然后發送 0x0 就可以選中溫度寄存器

                2. 選中溫度寄存器之后, LM75 會將 高/低 字節依次發送到I2C總線. 所以, 再次發送 LM75 地址, 讀取 高/低 字節  發送P信號結束傳輸.

int set_pointer_and_read_2byte(int mode)
{	
	//主機發送模式, 選中溫度寄存器
        I2C0.I2CDS0 = 0x90;                // 發送LM75地址 
	I2C0.I2CCON0 = 0xe0;                // 使能, PRESCALER:512 ,RX/TX 中斷使能
	I2C0.I2CSTAT0 =0xf0;                // 主發送模式, 啟動, 使能 RX/TX 
	while(!(I2C0.I2CCON0&(1<<4)));    // 等待直至發送完成 
	
	I2C0.I2CDS0 = mode;                // READ TEMPERATURE ONLY 讀取溫度寄存器
	I2C0.I2CCON0 &= ~(1<<4);            // 清除掛起標志 & 恢復總線操作 
	while(!(I2C0.I2CCON0&(1<<4)));    // 等待直至發送完成 
	
        //主機接收模式, 開始接收溫度數據
	I2C0.I2CDS0 = 0x91;                // 重新發送LM75地址 
	I2C0.I2CSTAT0 =0xb0;                // 主機接收模式, 啟動, 使能 RX/TX 
	I2C0.I2CCON0  &= ~(1<<4);            // 清除掛起標志 & 恢復總線操作 
	while(!(I2C0.I2CCON0&(1<<4)));        // 等待直至發送完成 

	I2C0.I2CCON0 &= ~(1<<4);             // 清除掛起標志 & 恢復總線操作 
	while(!(I2C0.I2CCON0&(1<<4)));        // 等待直至讀取完成 
	high = I2C0.I2CDS0;                // 讀取低8位數據 

	I2C0.I2CCON0 &= ~((1<<7)|(1<<4));// 清除掛起標志 & 恢復總線操作 & 禁止發送 ACK  
	while(!(I2C0.I2CCON0&(1<<4)));        // 等待直至讀取完成  
	low = I2C0.I2CDS0;                    // 讀取更低字節數據(小數部分 ?)  

	I2C0.I2CSTAT0 &= ~(1<<5);        // 發送 P信號, 釋放總線  
	I2C0.I2CCON0 &= ~(1<<4);        // 清除中斷標志位  
	return ((high << 8) | low);
}

到此,相信大家對“arm9 IIC接口有什么用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

威远县| 东丽区| 灵山县| 邯郸市| 廉江市| 岳普湖县| 威信县| 阿巴嘎旗| 霍邱县| 汨罗市| 湘潭市| 绵阳市| 遂平县| 会昌县| 吉首市| 怀远县| 两当县| 梅州市| 偏关县| 贵州省| 苍南县| 喀喇| 普安县| 扶绥县| 滨州市| 疏勒县| 河南省| 石泉县| 扎兰屯市| 呈贡县| 基隆市| 镇平县| 东源县| 类乌齐县| 南汇区| 宜兰县| 宁夏| 邹平县| 浮梁县| 来宾市| 西平县|