打印
[ZLG-ARM]

用LPC1343做一个可调数字电源和可调电子负载

[复制链接]
2602|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
米其林r|  楼主 | 2010-7-19 20:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
可调数字电源和可调电子负载基本功能如下:

    1、整机为220V交流供电,有交流变压器提供30V交流电,经过整流滤波后得到整机所需要的大约40V的原始电压。再由此得到OLED和MCU所需的15v、3.3V电压。

    2、数字电源和电子负载都有独立的显示部分,显示各自的状态信息。为了有一个好的显示效果,这里我用128*128的彩色OLED。

    3、数字电源部分为输出电压,输出电流,输出功率显示。电子负载部分为输入电压,消耗电流,消耗功率显示。
    4、数字电源开机初始状态为0V,可在0-30V范围内以0.1V步进电压调整(同时具有0.01v的微调按纽)。

    5、电子负载可以在0-2A吸取电流范围以0.1A步进调整(同时具有0.01A的微调按纽)。

    6、整机以LPC1343为中心:监测面板按键输入、控制两片OLED显示、PWM发生器、AD采样(输出电压、输出电流、输入电压,消耗电流)等。

    整体结构框图如下:


未命名.JPG (43.8 KB)

相关帖子

沙发
六楼的窗户| | 2010-7-19 20:27 | 只看该作者
采用的128*128 OLED是以前在TAOBAO上买到的,三星的(我比较讨厌这个品牌,刻录机、显示器用了,用了很短的时间都坏了,呵呵!)

本来我不会再买三星的品牌,这个是在淘宝上,当时也没有注意,处理的,价格好像只要10元,几乎白菜价了。

借用网上的图片,比我拍得好:


未命名.JPG (11.93 KB)
2010-7-2 08:16

使用特权

评论回复
板凳
金鱼木鱼| | 2010-7-19 20:28 | 只看该作者
OLED型号:PM12FC001B
规格:  1.52寸, 128×128    262K(18位的)。

编程说明书见附件,英文的。


OLED采用COB封装,大家看图片里面:驱动IC直接焊在软PCB上,IC的型号是LD50T6160。

引脚为43根,采用软PCB的铜帛。引脚很密,而且十分娇嫩:焊接的时候稍微用点力,引脚就会从软PCB上掉下来。



驱动好这个OLED需要两个电压: 一个是15V直流,驱动OLED点阵发光。一个是逻辑IC需要的工作电压,我们可以直接共用MCU的3.3V。



15V驱动消耗电流30mA左右,在设计电路时要考虑好。

数据总线可选6位或者18位的。我不想占用LPC1343太多的IO口,选6位数据总线。

使用特权

评论回复
地板
金鱼木鱼| | 2010-7-19 20:28 | 只看该作者
6位总线速度慢一点。我用GPIO模拟总线:
WRB: 为低时写入命令或者数据到OLED
A0: 为低时命令,为高时数据
DB5:0: 数据、命令总线

发送命令到OLED的函数:
void cmd(int a) //MCU送命令到OLED:PIO2_0:5为数据口;PIO1_0=A0; CSV=AD2;WRB=P1.5
{
LPC_GPIO[2]->MASKED_ACCESS[0x3f] = a; //PIO2_0:5=命令;
//delay1(10);
LPC_GPIO[1]->MASKED_ACCESS[0x01] = 0x00; //A0=0;
//delay1(10);
LPC_GPIO[3]->MASKED_ACCESS[0x01] = 0x00; //CSI=0;
//delay1(10);
LPC_GPIO[1]->MASKED_ACCESS[0x20] = 0x00; //WRB=0;
//delay1(10);
LPC_GPIO[1]->MASKED_ACCESS[0x20] = 0x20; //WRB=1;
//delay1(10);
LPC_GPIO[3]->MASKED_ACCESS[0x01] = 0x01; //CSI=1;
//delay1(10);
}

使用特权

评论回复
5
金鱼木鱼| | 2010-7-19 20:28 | 只看该作者
这里OLED显示速度的瓶井全部在GPIO口。



如果需要高速度可以从下面优化:



1、采用18位总线;



2、只需要写入OLED,不用考虑从OLED读出数据



3、CSB始终为有效,这样可以避免两次IO操作。



4、只在第一次写入数据时修改A0,以后写入数据时不要理会A0,减少IO操作。







采用以上优化后每个点的IO操作步骤只有原来的1/6。



对于128*128点阵的完全显示速度可以超过30桢。

使用特权

评论回复
6
金鱼木鱼| | 2010-7-19 20:29 | 只看该作者
void data(int a) //MCU写数据到OLED
{
LPC_GPIO[2]->MASKED_ACCESS[0x3f] = a; //PIO2_0:5=数据;
//delay1(10);
LPC_GPIO[1]->MASKED_ACCESS[0x01] = 0x01; //A0=1;
//delay1(10);
LPC_GPIO[3]->MASKED_ACCESS[0x01] = 0x00; //CSI=0;
//delay1(10);
LPC_GPIO[1]->MASKED_ACCESS[0x20] = 0x00; //WRB=0;
//delay1(10);
LPC_GPIO[1]->MASKED_ACCESS[0x20] = 0x20; //WRB=1;
//delay1(10);
LPC_GPIO[3]->MASKED_ACCESS[0x01] = 0x01; //CSI=1;
//delay1(10);
}

使用特权

评论回复
7
金鱼木鱼| | 2010-7-19 20:29 | 只看该作者
有了上面的对OLED发送命令和写入显示数据到OLED的函数,我们就很可以随心所欲的操作OLED了:
首先我们将OLED到LPC1343的控制线和数据线都设置为输出状态。OLED里面的数据我不关心(里面数据乱了顶多重写),所以RDB的线我直接接高电平。
其次:初始化OLED。
最后:把OLED整屏刷成白色,验证OLED是否正常顺便检查一下有没有坏点。有兴趣的朋友还可以刷成其他颜色。修改最后的FOR循环就可以了。

初始化代码如下:
void oledinit(void)
{
//初始化GPIO口,让CSI、CSV、A0、RSB、WRB都为输出(DIR位=1)IO2_0:5为输出
//CSI=1、CSV=1、A0=0、RSB=1、WRB=1;
LPC_IOCON->PIO2_0=0x50;
LPC_IOCON->PIO2_1=0x50;
LPC_IOCON->PIO2_2=0x50;
LPC_IOCON->PIO2_3=0x50;
LPC_IOCON->PIO2_4=0x50;
LPC_IOCON->PIO2_5=0x50;
LPC_GPIO[2]->DIR |= 0x3f; //对应位为1输出
LPC_GPIO[2]->MASKED_ACCESS[0x3f] = 0x00; //data=0,OLED命令模式,这是安全的GPIO设置

LPC_IOCON->JTAG_TMS_PIO1_0=0xd1; //数字上拉,IO口
LPC_GPIO[1]->DIR |= 1; //对应位为1输出
LPC_GPIO[1]->MASKED_ACCESS[0x01] = 0x00; //A0=0,OLED命令模式,这是安全的GPIO设置

LPC_IOCON->JTAG_TDO_PIO1_1=0xd1; //数字上拉,IO口
LPC_GPIO[1]->DIR |= 2; //对应位为1输出
LPC_GPIO[1]->MASKED_ACCESS[0x02] = 0x02; //CSV=1,取消选中OLEDV,这是安全的GPIO设置}

LPC_IOCON->PIO1_5=0x50;
LPC_GPIO[1]->DIR |= 0x20; //对应位为1输出
LPC_GPIO[1]->MASKED_ACCESS[0x20] = 0x20; //WRB=1,不写,这是安全的GPIO设置

LPC_IOCON->PIO1_8=0x50;
LPC_GPIO[1]->DIR |= 0x100; //对应位为1输出
LPC_GPIO[1]->MASKED_ACCESS[0x100] = 0x100; //RSB=1,不写,这是安全的GPIO设置

LPC_IOCON->PIO3_0=0x50;
LPC_GPIO[3]->DIR |= 0x01; //对应位为1输出
LPC_GPIO[3]->MASKED_ACCESS[0x01] = 0x01; //CSI=1,取消选中OLEDI,这是安全的GPIO设置

//初始化显示OLED
//standby on/off
//LPC_GPIO[1]->MASKED_ACCESS[0x100] = 0x00;
//delay1(1000);
//LPC_GPIO[1]->MASKED_ACCESS[0x100] = 0x100;
//delay1(1000);
cmd(0x03);
data(0x00); //off

//-----------------------------------------------------------------
// Panel Condition Set
//-----------------------------------------------------------------

//画面大小
cmd(0x07);
data(0x00);
data(0x00); //00
data(0x07);
data(0x0F); //127
data(0x02);
data(0x00); //32 //D-IC Change : 128128 IC -> 128160 IC
data(0x09);
data(0x0F); //159 //D-IC Change : 128128 IC -> 128160 IC

//write direction
cmd(0x05);
data(0x00);

//frame frequency
cmd(0x04);
data(0x01); //75Hz

//row overlap scan
cmd(0x1F);
data(0x00);

//internal regulator
cmd(0x30);
data(0x13); //internal regulator enable 80%

//-----------------------------------------------------------------
// Drive Condition Set
//-----------------------------------------------------------------

//precharge time
cmd(0x1C);
data(0x00);
data(0x04); //4?

//peak width
cmd(0x1D);
data(0x07); //red
data(0x08); //green
data(0x07); //blue

//output current
cmd(0x0E);
data(0x08);
data(0x02); //red
data(0x04);
data(0x0E); //green
data(0x03);
data(0x02); //blue

//-----------------------------------------------------------------
// Memory Data Write
//-----------------------------------------------------------------

//interface
cmd(0x08);
data(0x00); //=> 6bit 262k

//xbox size
cmd(0x0A);
data(0x00);
data(0x00); //00
data(0x07);
data(0x0F); //127
data(0x02);
data(0x00); //32
data(0x09);
data(0x0F); //159

//data write
cmd(0x0C);

//full white pattern write => 6bit 262k
int i,j;
for(i=0;i<128;i++)
{
for(j=0;j<128;j++)
{
data(0); //data write
data(0);
data(0);
}
}
}

使用特权

评论回复
8
金鱼木鱼| | 2010-7-19 20:30 | 只看该作者
为了保证这个项目有头有尾,特说明一下项目暂停的理由。
    对于这个电源和负载,其重要部分是对输出的电压和消耗电流采样并进行AD转换。并由这个AD结果对PWM部分的输出进行微调。
    LPC1343的AD部分参考电压是取自3.3V供电,没有单独的参考电压引脚,也没有内部的参考电源。当时也心存侥幸:应该也可以得到稳定的AD结果。
    可是从后面我做的一系列实验来看:AD结果调的实在太厉害了,10位的AD结果变动的位数应该有4位吧!
    当然我也做了一些努力。
    一、软件滤波。(借用一下八股文风格)
    最初我采用采样64次去掉最大值和最小值再取平均的做法,不过结果还是变动的厉害。
    考虑到可能只去掉一个最大值和一个最小值不能完全除去那些不稳定的AD结果,我又对64次结果去除最大的5个数和最小的5个数,再取平均值,函数如下:







//ADC结果滤波计算,先将N个结果都加起来(同时找到最大数和最小数),然后减去最大最小数除以N-2
int adcfilter(int* shujv ,int shucounter)
{
int jieguo=0,max=0,min=shujv[0];
int i,j;
for (i=1;i<shucounter;i++)
{
  j=0;
  while (j<i)
  {
   if (shujv[j]>shujv)
   {
    for (jieguo=j;jieguo<i;jieguo++)
    {
     max=shujv[jieguo];
     shujv[jieguo]=shujv;
     shujv=max;
    }
    j=i;
   }
   j++;















  }
}
jieguo=0;
if (shucounter<=10)
  j=0;
else
  j=5;
for (i=j;i<shucounter-j;i++)  //前后5个都不要
{
  jieguo +=shujv;
}
return jieguo;
}








    结果貌似稳定了一些,跳的慢了一些。不过后来发现这只是运算量大造成的系统反映慢而已,跳动范围还是很大的。
    二、对MCU提供3.3V的稳定电压。
    考虑到前面做的实验都是在开发板上,LPC1343使用下载器的3.3V电源,这个电压不稳定,偏低,而且受各种干扰源污染,AD结果当然不稳定拉。于是我把OLED的3.3V供电提供给LPC1343。这是由LM1117提供的,可以说电力十分稳定纯净。而且OLED的逻辑电路耗电很小,不会带来很多干扰。
    结果还是不理想, AD结果还是跳动。
    三、还有一种可能就是电压本身不稳定,这个不能怪LPC1343。
    我用万用表量了输出电压,万用表的读数基本不动。
    四、可能设计开发板时对AD通道没有做专门的考虑,也会导致AD结果不稳定。
    这个只有专门做板了。







    目前我用古老的MEGA8继续这个工作,结果十分顺利: MEGA8同样有10位的AD转换,有单独的参考电压引脚。不过我用了他内部的2.56V参考电压,AD结果很稳定,只有最低1位偶有跳动。

使用特权

评论回复
9
金鱼木鱼| | 2010-7-19 20:30 | 只看该作者
对于LPC1343的其他部分,我也正在不断体验中,觉得还不错。



    以上只是我用LPC1343的AD的体会,一家之言。十分希望大家有其他结论或者不同看法,特别欢迎有实际操作后的看法。

使用特权

评论回复
10
金鱼木鱼| | 2010-7-19 20:30 | 只看该作者
万用表本来就是量RMS值,不动也正常
用示波器看看~

我用周立功的Tiny-M0烧AD的例程,用杜邦线拉出来,效果蛮好的

使用特权

评论回复
11
最爱01间| | 2010-7-19 22:41 | 只看该作者
漂过!

使用特权

评论回复
12
lovedata| | 2010-7-20 08:56 | 只看该作者
好贴,顶!:D

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

340

主题

1587

帖子

3

粉丝