【TI首届低功耗设计大赛】空气参数记录仪(OLED调试阶段)
[复制链接]
本帖最后由 GaryTavish 于 2014-12-21 15:49 编辑
说来惭愧,一开始看到活动的通知就兴致勃勃的填写了申请,谁想到收到板子以后,生活里各种事情接踵而至,又是考试又是实习又是论文又是找工作,还有一堆人催着我做项目,真是分身乏术,好在工作的额事情已经落听,这才抽出时间来做设计大赛。
关于空气参数记录仪,其实就是一个可以记录空气温度湿度的设备,用于建筑物内的数据采集。这个东西半年前给学校里一个老师做了几个,用的是AVR的主控,传感器是ams2302,当时还加入了光照传感器记录建筑采光,每10分钟记录采样一次直接写在SD卡里,还用oled做了ui出来。所以这次也决定做这个,于是问题来了,首先需要调试好OLED才能显示界面。经过了今天一上午的调试成果如下。
一开始是打算用IAR+官方驱动库解决的,结果在HW SPI哪里卡了半天没搞明白,索性就先转战Energia去了,之前用G2553的时候自己在上面写了一个OLED的驱动,经过简单的修改,就转到了FR5969上面,由于oled用的1306主控扫描方式比较神奇,一共8个page,一个page是128*8bit所以使用起来主要难度在于图像的变换:
void OLED_SendRamBuff()
{
unsigned int pointer=0;
unsigned int temp=0x00;
digitalWrite(OLED_CS,LOW);
for(unsigned int page=0;page<8;page++)
{
digitalWrite(OLED_DC,LOW);
SPI.transfer(0xb0|page);
SPI.transfer(0x10);
SPI.transfer(OLED_TYPE);
digitalWrite(OLED_DC,HIGH);
for(unsigned int x=0;x<16;x++)
{
for(unsigned int b=0;b<8;b++)
{
temp=0x00;
for(unsigned int y=0;y<8;y++)
{
if((RamBuff[pointer]>>b)&0x01)
{
temp=temp|0x80;
}
if(y!=7)
{
temp=temp>>1;
pointer+=16;
}
}
SPI.transfer(temp);
pointer-=112;
}
pointer++;
}
pointer=(page+1)*128;
}
digitalWrite(OLED_CS,HIGH);
} 复制代码 顺便附上oled初始化代码(来自u8glib的启动参数):
static const unsigned char pram[] = {
0x0ae, /* display off, sleep mode */
0x0d5, 0x080, /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
0x0a8, 0x03f, /* */
0x0d3, 0x000, /* */
0x040, /* start line */
0x08d, 0x014, /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
0x020, 0x002, /* 2012-05-27: page addressing mode */
0x0a1, /* segment remap a0/a1*/
0x0c8, /* c0: scan dir normal, c8: reverse */
0x0da, 0x012, /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
0x081, 0x0cf, /* [2] set contrast control */
0x0d9, 0x0f1, /* [2] pre-charge period 0x022/f1*/
0x0db, 0x040, /* vcomh deselect level */
0x02e, /* 2012-05-27: Deactivate scroll */
0x0a4, /* output ram to display */
0x0a6, /* none inverted normal display mode */
0x0af
}; 复制代码 用
Energia实现显示以后,再回头来看IAR的官方驱动库。首先要说TI这个库写的挺良心的,SPI MASTER TX的例程还是用RX中断来实习的,但是在驱动oled的时候我们不需要它响应中断,只要一直发就行了,所以我重写了这部分:
uint8_t TXData = 0;
void main(void)
{
WDT_A_hold(WDT_A_BASE);//stop watchdog
//FRAM_configureWaitStateControl(FRAM_ACCESS_TIME_CYCLES_7); //if MCLK>8Mhz
CS_clockSignalInit(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);
CS_setDCOFreq(CS_DCORSEL_1, CS_DCOFSEL_4);
CS_clockSignalInit(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);//set DCO and MCLK SMCLK
GPIO_setAsOutputPin(
GPIO_PORT_P1,
GPIO_PIN2
);
GPIO_setOutputHighOnPin(
GPIO_PORT_P1,
GPIO_PIN2
);//enable p1.2 cs
EUSCI_B_SPI_disable(EUSCI_B0_BASE);//eUCSI in reset mode
GPIO_setAsPeripheralModuleFunctionInputPin(
GPIO_PORT_P2,
GPIO_PIN2,
GPIO_SECONDARY_MODULE_FUNCTION
);//set p2.2 to UCB0CLK
GPIO_setAsPeripheralModuleFunctionInputPin(
GPIO_PORT_P1,
GPIO_PIN6 + GPIO_PIN7,
GPIO_SECONDARY_MODULE_FUNCTION
);//set P1.6&7 to UCB0SPI
PMM_unlockLPM5();//unlock hi-z
EUSCI_B_SPI_masterInit(EUSCI_B0_BASE,
EUSCI_B_SPI_CLOCKSOURCE_SMCLK,
CS_getSMCLK(),
16000000,
EUSCI_B_SPI_MSB_FIRST,
EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT,
EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH,
EUSCI_B_SPI_3PIN
);
EUSCI_B_SPI_enable(EUSCI_B0_BASE);//enable spi
EUSCI_B_SPI_clearInterruptFlag(EUSCI_B0_BASE,
EUSCI_B_SPI_RECEIVE_INTERRUPT
);//clearflag
TXData=0x00;
for(int i=0;i<256;i++)
{
/*while (!EUSCI_B_SPI_getInterruptStatus(EUSCI_B0_BASE,
EUSCI_B_SPI_TRANSMIT_INTERRUPT));*/
while (!(UCB0IFG & UCTXIFG)); //very fast
GPIO_setOutputLowOnPin(
GPIO_PORT_P1,
GPIO_PIN2
);
EUSCI_B_SPI_transmitData(EUSCI_B0_BASE, TXData);
TXData+=0x01;
}
while (!EUSCI_B_SPI_getInterruptStatus(EUSCI_B0_BASE,
EUSCI_B_SPI_RECEIVE_INTERRUPT));
GPIO_setOutputHighOnPin(
GPIO_PORT_P1,
GPIO_PIN2
);
__no_operation();// remain in LPM0
} 复制代码 这样就实现了HW SPI发送,接下来只要把指令移植过来就能正常点亮oled了,在此说说调试时候的问题,首先要说的就是TX中断的FLAG,一开始手贱在发送之前把这个flag顺手给清了,结果这个flag也不会更新,必然无法发送。再一个就是MCLK的速度。在官方程序里写的是
Wait states are inserted automatically when the FRAM is accessed at speeds higher than 8MHz to prevent timing violations.但是实际上如果不手动FR AM_configureWaitStateControl(FRAM_ACCESS_TIME_CYCLES_7);一下,在MCKL快于8Mhz的时候就直接卡死了。经过测试eUSCI_B最快的发送速度差不多能到250KB/s,不知道用中断或者DMA的方式能不能更快一些。另外还发现了官方驱动库文档的一个小错误:
所有EUSCI_B里面的UCAxCTLW0其实都应该是
UCBxCTLW0吧。。。不知道官方有没有勘误。。
OLED测试时候,屏下缓存到屏上缓存进行坐标变换,速度还能达到30FPS的刷新速度,对比AVR的话真的是非常快,如果是输入和屏幕扫描格式一样的图片省去坐标变换,更是可以得到惊人的110FPS刷新速度,屏幕刷新都跟不上了。。。
先扯这么多。。接着搞代码去了。。求各路大神轻拍砖。。。。