四、重新设计之二
时间:10-02
整理:3721RD
点击:
在经过mbed的各种尝试之后,由于无法实现i2cmaster模式——也许这不是主要问题,但是读取RGBW传感器的数据始终不对,因此退而求标准开发模式。简化传输量,将lcm.h的改动部分放上来,没有改动的部分参照实验三。lcm.h改动的代码:
#include "chip.h"
#include "board.h"
#define SDA_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 24 )
#define SDA_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 24 )
#define SDA_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 24)
#define SCK_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0 ,25 )
#define SCK_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 25 )
#define SCK_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 25)
#define A0_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 26 )
#define A0_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 26 )
#define A0_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 26);
#define RST_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 13 )
#define RST_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0 , 13 )
#define RST_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 13)
#define CS_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 17 )
#define CS_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 17 )
#define CS_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 17)
#define LED_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 16 )
#define LED_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 16 )
#define LED_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 16)
... ...
//Delayer
void delay0(int counter){
int i;
for(i=0;i<counter;i++){;}
}
void setLcdGPIO(void){
SDA_DIR;
SCK_DIR;
A0_DIR;
RST_DIR;
CS_DIR;
LED_DIR;
}
//Write Plus
void wri(void){SCK_CLR;SCK_SET;}
//a B Data to LCD,dt:data,com:1-data/0-command
void b2l(unsigned char dt,unsigned char com){
unsigned char i;
CS_CLR;
if(com) A0_SET;else A0_CLR;
for(i=0;i<8;i++){
if(dt&0x80){SDA_SET;}else{SDA_CLR;};
dt=dt<<1;
wri();
}
CS_SET;
}
...
//END Files//
主函数main.cpp基本按照下载的源代码,只是在主函数中将测试4个数据用循环语句完成,代码短了一些,如下:
#include "board.h"
#include "lcm.h"
static I2CM_XFER_T i2cmXferRec;
#define I2C_CLK_divIDER (40)// System clock is set to 24MHz, I2C clock is set to 600kHz
#define I2C_BITRATE (100000)//100KHz I2C bit-rate
#define I2C_ADDR_7BIT (0x10)//7-bit I2C addresses of I/O expander Note: The ROM code requires the address to be between bits [6:0]||bit 7 is ignored
#define TICKRATE_HZ (100)//SysTick rate in Hz
#define TASK_LOOP while (true)
#define EVENT_LED_BUMP 0x01
#define EVENT_LED_TOGGLE 0x02
static volatile int intErrCode;
static volatile uint32_t ticks;
static uint8_t txData[16];
static uint8_t rxData[16];
static uint32_t event_flag,js;
static uint16_t rgb[4];
void Init_I2C_PinMux(void){
#if (defined(BOARD_NXP_LPCXPRESSO_812) || defined(BOARD_LPC812MAX) || defined(BOARD_NXP_LPCXPRESSO_824))
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM);
#if defined(BOARD_NXP_LPCXPRESSO_824)
Chip_SWM_EnableFixedPin(SWM_FIXED_I2C0_SDA);
Chip_SWM_EnableFixedPin(SWM_FIXED_I2C0_SCL);
#else
Chip_SWM_MovablePinAssign(SWM_I2C_SDA_IO, 10);
Chip_SWM_MovablePinAssign(SWM_I2C_SCL_IO, 11);
#endif
Chip_IOCON_PinSetI2CMode(LPC_IOCON, IOCON_PIO10, PIN_I2CMODE_FASTPLUS);
Chip_IOCON_PinSetI2CMode(LPC_IOCON, IOCON_PIO11, PIN_I2CMODE_FASTPLUS);
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM);
#else
#warning "No I2C pin muxing defined"
#endif
}
void dispBase(void);
void dispMes(void);
void delay(uint16_t counter){
int i,j;
for(i=0;i<counter;i++)
for(j=0;j<i;j++){;}
}
void setupI2CMaster(){
Chip_I2C_Init(LPC_I2C);//Define P0_11,P0_10 for I2C
Chip_I2C_SetClockDiv(LPC_I2C, I2C_CLK_divIDER);
Chip_I2CM_SetBusSpeed(LPC_I2C, I2C_BITRATE);
Chip_I2CM_Enable(LPC_I2C);
}
void SetupXferRecAndExecute(uint8_t devAddr,uint8_t *txBuffPtr,uint16_t txSize,uint8_t *rxBuffPtr,uint16_t rxSize){
i2cmXferRec.slaveAddr = devAddr;
i2cmXferRec.status = 0;
i2cmXferRec.txSz = txSize;//=2
i2cmXferRec.rxSz = rxSize;//=0
i2cmXferRec.txBuff = txBuffPtr;
i2cmXferRec.rxBuff = rxBuffPtr;
Chip_I2CM_XferBlocking(LPC_I2C, &i2cmXferRec);
}
void sendI2CMaster(uint16_t i2c_addr, uint32_t ledStateOut){
int index = 0;
txData[index++] = (uint8_t) 0x16; /* I2C device regAddr */
txData[index++] = (uint8_t) ((ledStateOut) & 0xff); /* I2C device regVal */
txData[index++] = (uint8_t) ((ledStateOut >> 8) & 0xff);/* I2C device regVal */
txData[index++] = (uint8_t) ((ledStateOut >> 16) & 0xff);/* I2C device regVal */
txData[index++] = (uint8_t) ((ledStateOut >> 24) & 0xff);/* I2C device regVal */
SetupXferRecAndExecute(i2c_addr, txData, 5, rxData, 0);
}
void SysTick_Handler(){
ticks++;
if ((ticks % 50) == 0){event_flag |= EVENT_LED_BUMP;}
if ((ticks % 125) == 0){event_flag |= EVENT_LED_TOGGLE;}
}
int main(){
uint16_t txSize,rxSize,last_Data;
uint8_t i,j,times=16;//LSB,MSB,;
uint32_t sum_data;
SystemCoreClockUpdate();
Board_Init();
Init_I2C_PinMux();
setupI2CMaster();
NVIC_DisableIRQ(I2C_IRQn);
setLcdGPIO();
lcdInit();
lcdClear();
dispBase();
txSize = 2;
rxSize = 0;
txData[0]=0x00;
txData[1]=0x10;// (0x10) [16] 2 [16] 0
SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);
delay(times);
last_Data=0;
txSize = 1;
rxSize = 2;
while(1){
//Test RGBW a Roller
for(j=0;j<4;j++){
txData[0]=0x08+j;
sum_data=0;
for(i=0;i<times;i++){ //0x10 0x08 1 [16] 2
SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);
delay(100);
last_Data=((rxData[1]<<8)+rxData[0]);
sum_data+=last_Data;
}
rgb[j]=sum_data/times;
}
js++;
dispMes();
LED_CLR;
delay(times*5);
LED_SET;
}
}
//Display Base
void dispBase(void){
c2l(0,0,42);c2l(0,1,51);//JS
c2l(1,0,33);c2l(1,1,16);c2l(1,8,33);c2l(1,9,17);//A0,A1
c2l(2,0,48);c2l(2,1,55);c2l(2,2,17);c2l(2,8,48);c2l(2,9,55);c2l(2,10,18);//PW0PW1
c2l(3,0,50);c2l(3,1,26);c2l(3,8,39);c2l(3,9,26);//R:G:
c2l(4,0,34);c2l(4,1,26);c2l(4,8,55);c2l(4,9,26);//b:W:
c2l(5,0,48);c2l(5,1,42);c2l(5,2,18);c2l(5,3,24);//PJ28
}
//Display Test
void dispMes(void){
c2l(0,3,16+(js/100000)%10);c2l(0,4,16+(js/10000)%10);c2l(0,5,16+(js/1000)%10);c2l(0,6,16+(js/100)%10);c2l(0,7,16+(js/10)%10);c2l(0,8,16+(js)%10);
c2l(3,3,16+(rgb[0]/1000)%10);c2l(3,4,16+(rgb[0]/100)%10);c2l(3,5,16+(rgb[0]/10)%10);c2l(3,6,16+(rgb[0])%10);
c2l(3,11,16+(rgb[1]/1000)%10);c2l(3,12,16+(rgb[1]/100)%10);c2l(3,13,16+(rgb[1]/10)%10);c2l(3,14,16+(rgb[1])%10);
c2l(4,3,16+(rgb[2]/1000)%10);c2l(4,4,16+(rgb[2]/100)%10);c2l(4,5,16+(rgb[2]/10)%10);c2l(4,6,16+(rgb[2])%10);
c2l(4,10,16+(rgb[3]/10000)%10);c2l(4,11,16+(rgb[3]/1000)%10);c2l(4,12,16+(rgb[3]/100)%10);c2l(4,13,16+(rgb[3]/10)%10);c2l(4,14,16+(rgb[3])%10);
}
改完的程序仅仅完成驱显,1个程序计数器和1只LED闪烁,ADC、PWM、脉冲产生、检测脉冲需要单独在编写。改回标准编码方法,函数的描述非常长,为了准确的描述一个函数,通常需要从某个变量开始搜索整个项目,而后找到对应函数;很多情况是函数套函数,搜到2~3级之后才能找到正确的变量描述和函数的使用。并且,从PIO的定义就可以看出:使用1个GPIO,需要定义口的输出、输出反向、开时钟、定义高或低,等等多个语句才能完成这个口,比起mbed来确是复杂了许多。这绝对不是编写代码的进步,也绝对不是编程人员的福音——倒是加速成为码农——当然,有些工具可以自动生成代码,但长度绝对可以成为想象中的码农采用机械来耕犁那一望无际的码。结果见照片31,32。程序改完后的运行可靠连续半天没有任何情况发生。需要说明的是循环语句中检测RGBW的循环无法摘出成为一个功能函数,结果是检测十分不稳定,少则几个,多则几分钟的采样数据屏幕就不动了。不知道是什么原因。成为独立函数模块后有些变量成为全局变量,有些事私有变量。这点可以大家一起分析找出原因。因为模块化是C的最爱。谢谢。
#include "chip.h"
#include "board.h"
#define SDA_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 24 )
#define SDA_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 24 )
#define SDA_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 24)
#define SCK_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0 ,25 )
#define SCK_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 25 )
#define SCK_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 25)
#define A0_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 26 )
#define A0_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 26 )
#define A0_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 26);
#define RST_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 13 )
#define RST_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0 , 13 )
#define RST_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 13)
#define CS_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 17 )
#define CS_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 17 )
#define CS_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 17)
#define LED_SET Chip_GPIO_SetPinOutHigh(LPC_GPIO_PORT, 0, 16 )
#define LED_CLR Chip_GPIO_SetPinOutLow(LPC_GPIO_PORT, 0, 16 )
#define LED_DIR Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 16)
... ...
//Delayer
void delay0(int counter){
int i;
for(i=0;i<counter;i++){;}
}
void setLcdGPIO(void){
SDA_DIR;
SCK_DIR;
A0_DIR;
RST_DIR;
CS_DIR;
LED_DIR;
}
//Write Plus
void wri(void){SCK_CLR;SCK_SET;}
//a B Data to LCD,dt:data,com:1-data/0-command
void b2l(unsigned char dt,unsigned char com){
unsigned char i;
CS_CLR;
if(com) A0_SET;else A0_CLR;
for(i=0;i<8;i++){
if(dt&0x80){SDA_SET;}else{SDA_CLR;};
dt=dt<<1;
wri();
}
CS_SET;
}
...
//END Files//
主函数main.cpp基本按照下载的源代码,只是在主函数中将测试4个数据用循环语句完成,代码短了一些,如下:
#include "board.h"
#include "lcm.h"
static I2CM_XFER_T i2cmXferRec;
#define I2C_CLK_divIDER (40)// System clock is set to 24MHz, I2C clock is set to 600kHz
#define I2C_BITRATE (100000)//100KHz I2C bit-rate
#define I2C_ADDR_7BIT (0x10)//7-bit I2C addresses of I/O expander Note: The ROM code requires the address to be between bits [6:0]||bit 7 is ignored
#define TICKRATE_HZ (100)//SysTick rate in Hz
#define TASK_LOOP while (true)
#define EVENT_LED_BUMP 0x01
#define EVENT_LED_TOGGLE 0x02
static volatile int intErrCode;
static volatile uint32_t ticks;
static uint8_t txData[16];
static uint8_t rxData[16];
static uint32_t event_flag,js;
static uint16_t rgb[4];
void Init_I2C_PinMux(void){
#if (defined(BOARD_NXP_LPCXPRESSO_812) || defined(BOARD_LPC812MAX) || defined(BOARD_NXP_LPCXPRESSO_824))
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM);
#if defined(BOARD_NXP_LPCXPRESSO_824)
Chip_SWM_EnableFixedPin(SWM_FIXED_I2C0_SDA);
Chip_SWM_EnableFixedPin(SWM_FIXED_I2C0_SCL);
#else
Chip_SWM_MovablePinAssign(SWM_I2C_SDA_IO, 10);
Chip_SWM_MovablePinAssign(SWM_I2C_SCL_IO, 11);
#endif
Chip_IOCON_PinSetI2CMode(LPC_IOCON, IOCON_PIO10, PIN_I2CMODE_FASTPLUS);
Chip_IOCON_PinSetI2CMode(LPC_IOCON, IOCON_PIO11, PIN_I2CMODE_FASTPLUS);
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM);
#else
#warning "No I2C pin muxing defined"
#endif
}
void dispBase(void);
void dispMes(void);
void delay(uint16_t counter){
int i,j;
for(i=0;i<counter;i++)
for(j=0;j<i;j++){;}
}
void setupI2CMaster(){
Chip_I2C_Init(LPC_I2C);//Define P0_11,P0_10 for I2C
Chip_I2C_SetClockDiv(LPC_I2C, I2C_CLK_divIDER);
Chip_I2CM_SetBusSpeed(LPC_I2C, I2C_BITRATE);
Chip_I2CM_Enable(LPC_I2C);
}
void SetupXferRecAndExecute(uint8_t devAddr,uint8_t *txBuffPtr,uint16_t txSize,uint8_t *rxBuffPtr,uint16_t rxSize){
i2cmXferRec.slaveAddr = devAddr;
i2cmXferRec.status = 0;
i2cmXferRec.txSz = txSize;//=2
i2cmXferRec.rxSz = rxSize;//=0
i2cmXferRec.txBuff = txBuffPtr;
i2cmXferRec.rxBuff = rxBuffPtr;
Chip_I2CM_XferBlocking(LPC_I2C, &i2cmXferRec);
}
void sendI2CMaster(uint16_t i2c_addr, uint32_t ledStateOut){
int index = 0;
txData[index++] = (uint8_t) 0x16; /* I2C device regAddr */
txData[index++] = (uint8_t) ((ledStateOut) & 0xff); /* I2C device regVal */
txData[index++] = (uint8_t) ((ledStateOut >> 8) & 0xff);/* I2C device regVal */
txData[index++] = (uint8_t) ((ledStateOut >> 16) & 0xff);/* I2C device regVal */
txData[index++] = (uint8_t) ((ledStateOut >> 24) & 0xff);/* I2C device regVal */
SetupXferRecAndExecute(i2c_addr, txData, 5, rxData, 0);
}
void SysTick_Handler(){
ticks++;
if ((ticks % 50) == 0){event_flag |= EVENT_LED_BUMP;}
if ((ticks % 125) == 0){event_flag |= EVENT_LED_TOGGLE;}
}
int main(){
uint16_t txSize,rxSize,last_Data;
uint8_t i,j,times=16;//LSB,MSB,;
uint32_t sum_data;
SystemCoreClockUpdate();
Board_Init();
Init_I2C_PinMux();
setupI2CMaster();
NVIC_DisableIRQ(I2C_IRQn);
setLcdGPIO();
lcdInit();
lcdClear();
dispBase();
txSize = 2;
rxSize = 0;
txData[0]=0x00;
txData[1]=0x10;// (0x10) [16] 2 [16] 0
SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);
delay(times);
last_Data=0;
txSize = 1;
rxSize = 2;
while(1){
//Test RGBW a Roller
for(j=0;j<4;j++){
txData[0]=0x08+j;
sum_data=0;
for(i=0;i<times;i++){ //0x10 0x08 1 [16] 2
SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);
delay(100);
last_Data=((rxData[1]<<8)+rxData[0]);
sum_data+=last_Data;
}
rgb[j]=sum_data/times;
}
js++;
dispMes();
LED_CLR;
delay(times*5);
LED_SET;
}
}
//Display Base
void dispBase(void){
c2l(0,0,42);c2l(0,1,51);//JS
c2l(1,0,33);c2l(1,1,16);c2l(1,8,33);c2l(1,9,17);//A0,A1
c2l(2,0,48);c2l(2,1,55);c2l(2,2,17);c2l(2,8,48);c2l(2,9,55);c2l(2,10,18);//PW0PW1
c2l(3,0,50);c2l(3,1,26);c2l(3,8,39);c2l(3,9,26);//R:G:
c2l(4,0,34);c2l(4,1,26);c2l(4,8,55);c2l(4,9,26);//b:W:
c2l(5,0,48);c2l(5,1,42);c2l(5,2,18);c2l(5,3,24);//PJ28
}
//Display Test
void dispMes(void){
c2l(0,3,16+(js/100000)%10);c2l(0,4,16+(js/10000)%10);c2l(0,5,16+(js/1000)%10);c2l(0,6,16+(js/100)%10);c2l(0,7,16+(js/10)%10);c2l(0,8,16+(js)%10);
c2l(3,3,16+(rgb[0]/1000)%10);c2l(3,4,16+(rgb[0]/100)%10);c2l(3,5,16+(rgb[0]/10)%10);c2l(3,6,16+(rgb[0])%10);
c2l(3,11,16+(rgb[1]/1000)%10);c2l(3,12,16+(rgb[1]/100)%10);c2l(3,13,16+(rgb[1]/10)%10);c2l(3,14,16+(rgb[1])%10);
c2l(4,3,16+(rgb[2]/1000)%10);c2l(4,4,16+(rgb[2]/100)%10);c2l(4,5,16+(rgb[2]/10)%10);c2l(4,6,16+(rgb[2])%10);
c2l(4,10,16+(rgb[3]/10000)%10);c2l(4,11,16+(rgb[3]/1000)%10);c2l(4,12,16+(rgb[3]/100)%10);c2l(4,13,16+(rgb[3]/10)%10);c2l(4,14,16+(rgb[3])%10);
}
改完的程序仅仅完成驱显,1个程序计数器和1只LED闪烁,ADC、PWM、脉冲产生、检测脉冲需要单独在编写。改回标准编码方法,函数的描述非常长,为了准确的描述一个函数,通常需要从某个变量开始搜索整个项目,而后找到对应函数;很多情况是函数套函数,搜到2~3级之后才能找到正确的变量描述和函数的使用。并且,从PIO的定义就可以看出:使用1个GPIO,需要定义口的输出、输出反向、开时钟、定义高或低,等等多个语句才能完成这个口,比起mbed来确是复杂了许多。这绝对不是编写代码的进步,也绝对不是编程人员的福音——倒是加速成为码农——当然,有些工具可以自动生成代码,但长度绝对可以成为想象中的码农采用机械来耕犁那一望无际的码。结果见照片31,32。程序改完后的运行可靠连续半天没有任何情况发生。需要说明的是循环语句中检测RGBW的循环无法摘出成为一个功能函数,结果是检测十分不稳定,少则几个,多则几分钟的采样数据屏幕就不动了。不知道是什么原因。成为独立函数模块后有些变量成为全局变量,有些事私有变量。这点可以大家一起分析找出原因。因为模块化是C的最爱。谢谢。
41-驱显效果示意
42-黄线框表示此LED闪烁