zoukankan      html  css  js  c++  java
  • (转)CortexM3 (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,把这个重复起始标志单数据发送?
  • 相关阅读:
    【算法】二分图的判定
    【模板】并查集 两种路径压缩写法(类模板和函数模板)
    【模板】堆的结构
    新疆大学OJ(ACM) 1099: 数列有序!
    新疆大学OJ(ACM) 1047: string 字符串排序
    新疆大学(新大)OJ xju 1010: 四个年级 C++ STL map 将4层循环优化成2层循环可解
    新疆大学(新大)OJ xju 1009: 一带一路 prim求最短路径+O(n)素数筛选
    新疆大学(新大)OJ xju 1006: 比赛排名 第二类斯特林数+阶乘
    【算法】第二类斯特林数Stirling
    【复习资料】编译原理中:短语,直接短语,句柄
  • 原文地址:https://www.cnblogs.com/tdyizhen1314/p/2704604.html
Copyright © 2011-2022 走看看