(轉)Cortex-M3 (NXP LPC1788)之IIC應用--PCA9532進行IO擴展和LED亮度控制


 PCA9532是一個I2C接口的設備,可以用於IO的擴展和LED的亮度調節。它內部集成了振盪器,可以輸出2路用戶可編程的PWM波,周期從6.58ms到1.69S。16路的輸出,可以設置成輸出高低電平以及PWM波輸出。

        做為從設備,他的8位地址的高四位固定為1100,最低位為數據的方向位,剩下的3位有硬件連線確定他的地址。PCA9532共有10個寄存器來配置他的輸出狀態。

其中INPUT0 INPUT1在管腳配置成普通IO時候用於讀入IO腳的狀態。PSC0 PWM0 PSC1 PWM1用於設置兩路PWM波的周期和占空比。LS0~LS3用於選擇每個管腳的功能,包括通用LED OFF、LED ON、 PWM0、 PWM1。

        知道了需要配置的寄存器,那怎么通過I2C通信來配置這幾個寄存器呢?當LPC1788發出PCA9532的地址得到應答后,需要發送一個字節的數據用於配置控制寄存器,他們第四位為B3~B0位,比如發送的字節第4位為0,即B3~B0為0則他接下去收到的數據用來配置INPUT0。配置寄存器的第4位為AI,即autoincrease,表示接收到一個字節的配置數據后,是否自動的將B3~B0加1,方便配置下一個表中的寄存器。

        開發板上的PCA9532的電路圖如下

        程序中配置LED0~7為GPIO用於檢測按鍵,LED8~LED11配置成PWM輸出,將LED RED做出漸亮漸暗的效果,LED12~LED15根據按鍵值設置成LED ON 或LED OFF。按鍵值讀取PCA9532的INPUT0得到。程序如下

  1. #define PCLK    60000000 
  2. #define I2C0SCK  100000 
  3. #define PCA9532_ADDRESS 0x60 
  4.  
  5. #define rI2C0CONSET (*(volatile unsigned*)(0x4001C000)) 
  6. #define rI2C0CONCLR (*(volatile unsigned*)(0x4001C018)) 
  7. #define rI2C0STAT   (*(volatile unsigned*)(0x4001C004)) 
  8. #define rI2C0DAT    (*(volatile unsigned*)(0x4001C008)) 
  9. #define rI2C0SCLH   (*(volatile unsigned*)(0x4001C010)) 
  10. #define rI2C0SCLL   (*(volatile unsigned*)(0x4001C014)) 
  11.  
  12. #define rIOCON_P0_27    (*(volatile unsigned *)(0x4002C06C)) 
  13. #define rIOCON_P0_28    (*(volatile unsigned *)(0x4002C070)) 
  14.  
  15. #define rPCONP      (*(volatile unsigned*)(0x400FC0C4)) 
  16.  
  17. unsigned char config[11], read_data[1]; 
  18. void I2C0_Init() 
  19.     rIOCON_P0_27 = (rIOCON_P0_27&(~0x7))|0x1;   //I2C0_SDA 
  20.     rIOCON_P0_28 = (rIOCON_P0_28&(~0x7))|0x1;   //I2C0_SCL 
  21.     rPCONP |= 0x1<<7;   //I2C0 Power Enable  
  22.     rI2C0SCLH = PCLK/I2C0SCK/2;                 //set I2C0 frequency 100khz 
  23.     rI2C0SCLL = PCLK/I2C0SCK/2; 
  24.     rI2C0CONSET |= 0x1<<6;                       //I2C接口使能 
  25.     rI2C0CONCLR = 0x1<<3|0x1<<5;                //清除SI STA  
  26.  
  27. unsigned char I2C0_Start() 
  28.     rI2C0CONCLR = 0x1<<3;               //清除SI標志 
  29.      
  30.     rI2C0CONSET |= 0x1<<5;              //置位STA進入主發送模式 
  31.      
  32.     while(!(rI2C0CONSET&(0x1<<3)));     //起始條件發送完成 
  33.      
  34.     rI2C0CONCLR = 0x1<<5;               //清除STA標志 
  35.      
  36.     return (rI2C0STAT&0xF8); 
  37.  
  38. void I2C0_Stop() 
  39.     rI2C0CONCLR = 0x1<<5;               //清除STA標志 
  40.     rI2C0CONSET |= 0x1<<4;              //發送STO標志 
  41.     rI2C0CONCLR = 0x1<<3;               //清除SI標志 
  42.  
  43. unsigned char I2C0_SentByte(unsigned char data) 
  44.     rI2C0DAT = data; 
  45.      
  46.     rI2C0CONCLR = 0x1<<3;               //清除SI標志 
  47.      
  48.     while(!(rI2C0CONSET&(0x1<<3)));     //發送完數據得到了應答  
  49.   
  50.     return (rI2C0STAT&0xF8); 
  51.  
  52. unsigned char I2C0_GetByte(unsigned char* data, unsigned char ack_flag) 
  53.     if(ack_flag) 
  54.     { 
  55.         rI2C0CONSET |= 0x1<<2;              //主接收模式,接收到一個字節返回應答 
  56.     } 
  57.     else 
  58.     { 
  59.         rI2C0CONCLR = 0x1<<2;               //主接收模式,接收最后一個字節時,不返回應答 
  60.     } 
  61.     rI2C0CONCLR = 0x1<<3;                   //清除SI標志 
  62.     while(!(rI2C0CONSET&(0x1<<3)));         //發送完數據得到了應答  
  63.     *data = (unsigned char)rI2C0DAT; 
  64.     return (rI2C0STAT&0xF8); 
  65.  
  66. int I2C0_MasterTransfer(unsigned char slave_address, unsigned char *transfer_data, unsigned int transfer_count,\ 
  67.                     unsigned char *receive_data, unsigned int receive_count) 
  68.     unsigned char status; 
  69.     unsigned int i; 
  70.     
  71.     status = I2C0_Start(); 
  72.     while(status != 0x08); 
  73.      
  74.     status = I2C0_SentByte(slave_address<<1); 
  75.     while(status != 0x18); 
  76.      
  77.     for(i=0; i<transfer_count; i++) 
  78.     { 
  79.         status = I2C0_SentByte(*(transfer_data+i)); 
  80.         while(status != 0x28); 
  81.     } 
  82.     
  83.     if(receive_data!=(void*)0 && receive_count!=0) 
  84.     { 
  85.         //進入主接收模式 
  86.         status = I2C0_Start(); 
  87.         while(status != 0x10); 
  88.          
  89.         status = I2C0_SentByte((slave_address<<1)|0x1); 
  90.         while(status != 0x40); 
  91.          
  92.         for(i=0; i<receive_count; i++) 
  93.         { 
  94.             if(i<receive_count-1) 
  95.             { 
  96.                 status = I2C0_GetByte(receive_data, 1); 
  97.                 while(status != 0x50); 
  98.             } 
  99.             else 
  100.             { 
  101.                 status = I2C0_GetByte(receive_data, 0); 
  102.                 while(status != 0x58); 
  103.             } 
  104.             receive_data++; 
  105.         } 
  106.     } 
  107.  
  108.  
  109.     I2C0_Stop(); 
  110.      
  111.     return 1; 
  112.  
  113. void PCA9532_Config() 
  114.     config[0] = 0x1<<4;     //讀寫控制寄存器后低四位自動增加 
  115.     config[1] = 0;          //input0 
  116.     config[2] = 0;          //input1 
  117.     config[3] = 0;          //PSC0    PWM0的周期6.5ms 
  118.     config[4] = 0;          //PWM0    PWM0占空比設置成0% 
  119.     config[5] = 0;          //PSC1    PWM1的周期為6.5ms 
  120.     config[6] = 0;          //PWM1    PWM1占空比設置成0% 
  121.     config[7] = 0;          //LS0 
  122.     config[8] = 0;          //LS1     LED0~7 設置成GPIOS 
  123.     config[9] = 0xFA;       //LS2     11111010, LED8,9->blinks PWM0; LED10,11->blinks PWM1 
  124.     config[10] = 0;         //LS3     LED12~LED15, LED off 
  125.  
  126.  
  127.  
  128. int main(void
  129.     unsigned char flag=1, data=0; 
  130.     unsigned int i; 
  131.     I2C0_Init(); 
  132.     PCA9532_Config(); 
  133.     while(1) 
  134.     { 
  135.         I2C0_MasterTransfer(PCA9532_ADDRESS, config, sizeof(config), 0, 0); 
  136.          
  137.         I2C0_MasterTransfer(PCA9532_ADDRESS, &data, 1, read_data, 1);         
  138.          
  139.         if(flag) 
  140.         { 
  141.             config[4]++; 
  142.             config[6]++; 
  143.         } 
  144.         else 
  145.         { 
  146.             config[4]--; 
  147.             config[6]--; 
  148.         } 
  149.          
  150.         if(config[4]==255 || config[4]==0) 
  151.         { 
  152.             flag = !flag; 
  153.         } 
  154.          
  155.         for(i=0; i<4; i++) 
  156.         { 
  157.             if(read_data[0]&(0x1<<i)) 
  158.             { 
  159.                 config[10] &= ~(0x3<<(i*2)); 
  160.                  
  161.             } 
  162.             else 
  163.             { 
  164.                 config[10] |= (0x1<<(i*2)); 
  165.             } 
  166.         } 
  167.          
  168.     } 
  169. 程序調試過程中遇到如下問題,要注意:
            1,I2C控制清除寄存器為只讀,因此不能進行|=操作,否則狀態寄存器的值異常。不知道為什么不是產生異常復位,之前EEPROM也對只讀寄存器進行該操作會產生系統異常進入異常中斷。
            2,在主發送模式切換到主接收模式的過程中,一定要先清除SI標志。開始沒注意,發送重復起始表示后的狀態一直是0x28,把這個重復起始標志單數據發送?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM