从时序图中我们可以分析出,采用SPI通信接口与MAX7219芯片通信时,CPOL=0(串行同步时钟的空闲状态为低电平),CPHA=0,这点在编写程序时比较重要。
关于MAX7219的资料见附件,这里不再详细说明。简单介绍一下初始化步骤:
1. 设置解码模式,地址0x09,指令0xff(对0~7位数码都解码)
2. 设置亮度,地址0x0a,指令0x08。
3. 设定扫描控制,地址0x0b,指令0x07(扫描0~7位)。
4. 设定
电源模式,地址0x0c,指令0x01(正常显示模式)。
完成以上初始化步骤后,想在对应位置显示某个数字,只要向0x01~0x08位写入相应的数字就可以显示了。以下是一个简单的显示程序:
#include "mbed.h"
SPI max_7219(D11,D12,D13);
DigitalOut PIN_CS(D8);
DigitalOut myled(D2);
void max7219_init(void); //7219初始化函数
void max7219_write(int addr,int val); //7219写数据函数
charbuffer[]={0x05,0x02,0x00,0x01,0x03,0x01,0x04}; //显示的数字
char code[]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; //8个位的数据寄存器
int main()
{
max_7219.format(8,0);
max_7219.frequency(1000);
max7219_init();
int i,j=7;
for(i=0;i<8;i++)
{
max7219_write(code,buffer[j]|0x80);
j--;
//wait(1);
myled=!myled;
}
//while(1);
}
void max7219_write(int addr,int val)
{
PIN_CS = 0;
max_7219.write(addr);
max_7219.write(val);
PIN_CS = 1;
}
void max7219_init(void)
{
max7219_write(0x09,0xff); //解码模式
max7219_write(0x0a,0x08); //设置亮度
max7219_write(0x0b,0x07); //扫描控制
max7219_write(0x0c,0x01); //正常显示
//max7219_write(0x0f,0x00); //显示检测,可以省略
myled = 1;
}
这样的方式显示起来比较麻烦,我们可以尝试写一个库,把常用的功能用库函数的方式呈现出来,方便调用。下面的例子就用到了笔者自己编写的一个MAX7219的驱动库,它可以显示整数和浮点数,使用起来非常简单。现在我们写一个程序,用ADC采集电压,然后在数码管上显示。主程序很简单,如下:
#include "mbed.h"
#include "Smg_7219.h"
Serial pc1(USBTX,USBRX);
AnalogIn light(A0);
Smg_7219 my7219(D11,D12,D13,D8);
float value;
int main(void)
{
while(1)
{
value= light.read();
my7219.ShowFnum(value*3.3);
pc1.printf("value is %fn",value*3.3);
wait_ms(500);
}
}
这里包含了笔者编写的数码管驱动库Smg_7219.h,这里只实现了两个函数,一个用来显示整数void ShowNum(float num),一个用来显示浮点数void ShowFnum(float num),源代码会在附件里提供下载,感兴趣的读者可以自行扩充。程序思路很简单,采集A0口的电压,在数码管上显示电压值,同时在串口输出,每500ms采样一次。A0口采样的电压由光敏电阻和电阻分压得到。
下面是实验现象:
较强光照下电压为1.8V左右(采集的是光敏电阻和地之间的电压,下同)
强光下电压为0.87V左右
串口收到的数据
这里谈一点自己的体会吧,虽然这个库很简单,用户函数只有两个,但是在编写时花费的时间也有大半天,后面调试加上下载验证,功能改进等又过去了大半天,总耗时将近一天。实际上,这应该是笔者第一个用C++编写的驱动库(以前都是用C),虽然很艰难,但总归迈出了第一步。官方提供的库函数如DigitalInOut、AnalogIn等,用起来很简单,但是自己动手写一个简单的库却并不容易,学习得越深入,越感觉mbed确实非常好用和易用,大大简化了底层驱动,灵活性很强。另一方面,mbed的库仅仅提供了基础的功能,以
STM32的GPIO为例,根据官方库函数,其输出可以配置成不同的模式,如推挽输出、开漏输出、复用输出等,其输出还可设定输出速率以减小功耗。在mbed里就直接简化为输入和输出两种。同理,其他片上外设也做了简化。这是一种通过牺牲复杂的功能来换取易用性的尝试,可以说有得有失,这也是一种中庸之道吧。
下期将带来LCD1602液晶的讲解。