在线时间12 小时
UID343942
ST金币0
蝴蝶豆0
注册时间2012-2-25
初级会员
- 最后登录
- 1970-1-1
|
a0a.1 32b0c
本帖最后由 蹦蹦虾 于 2015-1-12 10:56 编辑
方案名称:家居LED显示屏
设计理念:替代家里的传统时钟显示。
功能概述:1.显示采用LED显示模组支持单色、双色、全彩户内灯板。
2.具有时钟显示功能。
3.具有温湿度采集显示功能。
4.具有空气质量传感器采集,显示功能。
5.为了增加可玩性,增加了蓝牙串口通信功能,这样就可以跟手机通信完成更多的功能。
6.增加手机留言功能。
7.增加学习2262,2272编码器功能,这样就可以用手机控制支持2262,2272遥控的家用电器,比如灯光,可遥控插座等。
系统框图
原理框图
配套硬件选择:
LED显示屏接口方式比较多,主要是08接口12接口75接口,08接口主要是户内的单元板,12接口是户外模组,75接口是全彩模组。这里先选用比较简单的16扫的户内08接口作为主显示屏。
所以LED引脚在学习板中的硬件引脚定义如下:
BusOut outline(PC_14,PC_15,PF_0,PF_1);//行输出选择
DigitalOut ledclk(A0);//时钟
DigitalOut ledst(A1);//锁存
DigitalOut ledoe(A2);//OE极性
DigitalOut ledr1(PC_2);//红色数据1
DigitalOut ledr2(PC_3);
DigitalOut ledg1(PC_12);//绿色数据1
DigitalOut ledg2(PD_2);
DigitalOut ledb1(PC_10);//蓝色数据1
DigitalOut ledb2(PC_11);
无线接收模块的选择用普通的315M接收发送模块,功能实现起来简单但是只能实现单一频段的发码和收码,支持的设备比较少,CC1101支持ASK,FSK得多种调制方式和灵活的配置寄存器的改变通信频率的方法。如果运用的好的话会支持很多市面上现有的无线通信设备。但是调试难度比较大作为备选方案。
可以用外置的时钟模块,也可以用学习板自带的时钟功能,这个测试看下精度在定。
具体功能会随着调试进程逐渐发布。
2015/1/12
MBED开发现在还不会导出,先贴出部分主函数,并讲解一下大概的思路。
#include "LED_Display.h"
#include "Time_Display.h"
#include "mbed.h"
Ticker RefreshRow,ScreenChange,flipper;
DigitalOut led1(LED1);
void flip() {
led1 = !led1;
}
LEDScreen led(A0, A1, A2, PC_2, PC_3, PC_12, PD_2, PC_10, PC_11, PC_14, PC_15, A3, A4);
SceneContent Area1;//分区1
SystemTime Time1;
int main(){
char m;
Time1.Time_Set(0,9,12,21,3,114);
flipper.attach(&flip, 1.0);//LED
led.Screen_Size(32,8,0);
Area1.Display_Locale(0,0,16,8,RB0);
// m=Area1.DirectScreen();
RefreshRow.attach_us(&led, &LEDScreen::Screen_Refresh, 1000); // the address of the object, member function, and interval
while(1) {
if(P1_Sign==0){ //幕开始 //设置幕参数
m=Screen_Count1*4;
Change_type=Play_content1[0+m];//变化内容
Change_mode=Play_content1[1+m];//变化模式
Change_Speed=Play_content1[2+m];//变化速度
ResidenceTime=Play_content1[3+m]*100;//停留秒数
Area1.GetDisplayData();//获取幕内容
ScreenChange.attach_us(&Area1, &SceneContent::TimingChange, 10000);//开启定时器
P1_Sign=1;
if(Screen_Count1>=2)
Screen_Count1=0;
else
Screen_Count1++;
}
}
}
上面2个头文件一个是LED显示屏的设置,一个是主芯片时钟功能设置。
主函数中先设置时间
Ticker RefreshRow,ScreenChange,flipper; 先定义3个定时器,定时中断执行不同的功能。 RefreshRow用来定时刷新LED显示屏,ScreenChange用来更新显示内容。flipper用来定时学习板上的LED指示灯显示。
DigitalOut led1(LED1); 定义学习板上LED指示灯的闪烁引脚定义。void flip() 函数让控制LED指示灯的引脚翻转。
LEDScreen led(A0, A1, A2, PC_2, PC_3, PC_12, PD_2, PC_10, PC_11, PC_14, PC_15, A3, A4); 生成LED显示屏对象
SceneContent Area1;//分区1 生成分区对象 分区的对象的意思是假设显示屏是64*64的点阵我想在上面32*64的点阵显示时间,下面32*64的点阵显示文字,就需要把实际屏体的点阵做好分区。
SystemTime Time1; 生成时间对象
主函数中先设置系统时间。
LED指示灯闪烁的方法
设置屏幕大小的方法
分区的设置,参数分别为起点的X坐标,Y坐标,分区的高,分区的长和读取数据的缓冲区的首地址。
然后再生产一个每隔1MS刷新LED显示屏行数据的方法。
主循环中先从一个节目数组中,读出显示一个分区一幕数据的,变化内容,变化模式,变化速度,和停留时间。
然后获取显示内容,因为在开启变化内容速度的计时器中断方法。P1_Sign1为分区1正在显示标志位。显示结束后会在中断方法中置零。这样就可以显示下一幕数据。下一幕数据标志位为Screen_Count1。
因为时间的问题现在只做了2个节目,一个开机的欢迎画面,一个是显示时间。函数如下:
//---------------------- 显示开机画面----------------------------
void SceneContent:isplayDataOfBoot(void)
{
LoadByteToDisBuf(AsciiCodeTab,'w',0);
LoadByteToDisBuf(AsciiCodeTab,'e',1);
LoadByteToDisBuf(AsciiCodeTab,'l',2);
LoadByteToDisBuf(AsciiCodeTab,'c',3);
LoadByteToDisBuf(AsciiCodeTab,'o',4);
LoadByteToDisBuf(AsciiCodeTab,'m',5);
LoadByteToDisBuf(AsciiCodeTab,'e',6);
LoadByteToDisBuf(AsciiCodeTab,' ',7);
}
/*******************************************
* 显示时间 *
********************************************/
void SceneContent:isplayTimeOfToday()
{
time_t seconds = time(NULL);//获取实时时间
Time[SEC]=char(seconds%60);
Time[MIN]=char((seconds/60)%60);
Time[HOU]=char((seconds/3600)%24);
LoadByteToDisBuf(AsciiCodeTab,Time[SEC]%10+48,7);
LoadByteToDisBuf(AsciiCodeTab,Time[SEC]/10+48,6);
LoadByteToDisBuf(AsciiCodeTab,':',5);
LoadByteToDisBuf(AsciiCodeTab,Time[MIN]%10+48,4);
LoadByteToDisBuf(AsciiCodeTab,Time[MIN]/10+48,3);
LoadByteToDisBuf(AsciiCodeTab,':',2);
LoadByteToDisBuf(AsciiCodeTab,Time[HOU]%10+48,1);
LoadByteToDisBuf(AsciiCodeTab,Time[HOU]/10+48,0);
}
函数在获取内容中调用函数如下:
//----------取出一幕内容到缓冲区 ----------------
//缓冲区首地址,内容类型
void SceneContent::GetDisplayData()
{
switch(Change_type) //扫描
{
case 0x00: DisplayDataOfBoot();break;//欢迎使用
case 0x01: DisplayTimeOfToday();break;
//case 0x02: DisplayDateOfToday(addr);break;
//case 0x03: DisplayYearOfToday(addr);break;
//case 0x04: DisplayWeekOfToday(addr);break;
//case 0x05: DisplayOfTemp(addr);break;
case 0x06: break;
case 0x07: break;
case 0x08: break;
default: DisplayDataOfBoot();break;
}
Change_Count=0;//变化计数
Change_sign=1;//进入变化
}
变化的具体方法还没有优化,需要不断调试函数如下:
//----------显示一幕变化 ----------------
//显示所在分区位置,分区大小,缓冲区地址,数据内容,变化方式 有溢出风险如果缓冲区大于实际显示面积
char SceneContent:isplayChange()
{
switch(Change_mode) //变化模式
{
case 0x00: Change_Count=DirectScreen();return Change_Count;//变化计数;//立即显示
case 0x01: Change_Count=LeftMoveScreen(Change_Count);return Change_Count;//左移显示
case 0x02: Change_Count=UpCoverScreen(Change_Count);return Change_Count;//上覆盖
case 0x03: Change_Count=DownCoverScreen(Change_Count);return Change_Count;//下覆盖
case 0x04: Change_Count=UpMoveScreen(Change_Count);return Change_Count;//上移
case 0x05: Change_Count=DownMoveScreen(Change_Count);return Change_Count;//下移
//case 0x06: return m;
//case 0x07: return m;
//case 0x08: return m;
default: Change_Count=DirectScreen();return Change_Count;//立即显示
} //根据变化计数,和分区位置。写入显存区
}
因为我的LED显示屏在测试的时候不幸烧了一下,好像烧断了一个行线,现在显示屏只显示上半部分,稍后奉上显示图片。
|
|