所有关于电路
项目

如何显示一个图像使用EFM8单片机液晶吗

2015年7月24日,通过罗伯特Keim

使用EFM8的USB功能将一个图像从你的电脑液晶显示器。

学习如何使用EFM8的USB功能将一个图像从你的电脑液晶显示器。

推荐的水平

中间

本系列之前的文章

所需的硬件/软件

项目概述

在以前的项目中,我们探索了实现EFM8 SPI的功beplay体育下载不了能,与液晶模块,格式和印刷10-by-8-pixel字符,并建立EFM8之间的USB连接和SciLab使用VCPXpress库。当前项目带来这些功能共同有效而方便地显示128 - LCD - 128像素的图像。目标是先从任何标准灰度. bmp图像文件并使用Scilab处理它,然后将它通过USB接口传输到EFM8单片机,这样我们才能显示它在128 - 128像素液晶。这个项目流程只有一个图片,但是这里提出的技术可以轻易地适应显示一个简单的动画由一系列类似的图像。

这个过程始于创建图像的使用Paint.NET或其他图像编辑应用程序。这张照片是加载到Scilab,加工成一种格式兼容的LCD,像素数据转化为一个矩阵,通过64字节的USB传输数据包EFM8。然后使用一个更新的SPI状态机转移这个像素数据,一次四行,LCD模块。

端口I / O

端口I / O配置是相同的,我们在前一篇文章中使用。

SPI信号映射到相应的端口别针,除了芯片选择信号,我们通过P0.1手动驱动。我们不需要直接配置端口USB数据行针;所有USB外设通过VCPXpress库初始化完成。

外设和中断

外围和中断的设置是相同的我们使用在上一篇文章:SPI与液晶模块,配置为通信和Timer4用于短延迟。我们不使用Timer2在这个项目中,因为我们不需要一个帧速率。顺序相反,更新液晶像素数据从PC接收数据包。

固件

VCP配置对于这个项目我们先前的项目中使用的是相同的。不过,有一些额外的USB功能:之前从Scilab EFM8只接收的数据,而现在还EFM8传送数据。

空白USBTxByte (unsigned char BytetoSend) {Block_Write (&BytetoSend 1 &USBBytesTransmitted);}

正如其名称所暗示的Block_Write()函数,VCPXpress图书馆能够传输的字节数组只有一个函数调用。然而,在这个项目中USB传输从EFM8仅用于流量控制:EFM8发送一个字节通知Scilab,是时候发送更多的数据。所以USBTxByte()函数是一个简单方便的方式使用Block_Write()发送一个字节。

USB接收数据包处理下面的代码:

如果(API_InterruptCode & RX_COMPLETE) / / USB读完整{如果(USBBytesReceived = = 1 & & USBRxPacket [0] = = NEW_IMAGE_FLAG) {CLEAR_LCD = TRUE;NextLinetoWrite = 0;/ /返回新形象标志字节流量控制的PC USBTxByte (NEW_IMAGE_FLAG);/ /继续下一个USB阅读过程Block_Read (USBRxPacket, USB_PACKET_SIZE &USBBytesReceived);}else if (USBBytesReceived = = USB_PACKET_SIZE){/ *这个标志告诉ImagetoLCD_main while循环。c处理收到的USB像素数据分组* / USB_PACKET_RECEIVED = TRUE;/ /继续下一个USB阅读过程Block_Read (USBRxPacket, USB_PACKET_SIZE &USBBytesReceived);}}

Scilab脚本完成时将图像文件转换为液晶像素数据,它发送一个1字节数据包ImagetoLCD_Defs中定义的值。NEW_IMAGE_FLAG h。因此,如果接收到的数据包长度是一个和单一接收字节的值为NEW_IMAGE_FLAG,单片机知道一个新形象。清除液晶,NEW_IMAGE_FLAG传送到电脑,和零装入NextLinetoWrite,这是一个变量保存第一行地址更新当单片机接收到下一个像素的数据包。如果接收到的数据包长度是64字节,而不是一个字节的数据包将实际的像素数据。在这种情况下,我们只是将USB_PACKET_RECEIVED标志设置为true;流控制字节将传播液晶更新完成后。

当ImagetoLCD_main的无限循环。c意识到USB_PACKET_RECEIVED被设置为true,它调用ProcessUSBRxPacket ():

空白ProcessUSBRxPacket () {unsigned char n = 0,行,列;/ /接收到的像素数据复制到液晶显示器数据数组(行= 0;行< LINES_PER_PACKET;行为(+ +){列= 0;列< NUM_LINE_DATA_BYTES;列+ +){LCDDisplayData(行)(列)= USBRxPacket [n];n + +;}}/ /等到SPI状态变量表示总线是用于一个新的转移而(LCDTxState ! =闲置);UpdateLCDLines ();}

这里我们将像素数据到相应的二维数组。在这个项目中,LCDDisplayData[][]是4行16列:我们仍然需要16列的128位字节持有水平数据,但是我们只需要4行因为像素数据从64年的个人电脑传输字节数据包,和64字节/每行16字节= 4行。更新数组后,程序将等待LCD通信接口是空闲,然后调用UpdateLCDLines ()。

这个项目需要一些改变液晶状态机管理SPI转移。以前我们UpdateAllLCDLines()函数,该函数(您可能猜到的名字)发起流程,更新所有液晶线在一个SPI转移。但是现在我们只更新四行一SPI转移中,和两个额外的任务执行的程序:

ImagetoLCD.zip

Scilab

Scilab脚本始于一个图像处理部分:

必须将输入图像灰度级,128 -,- 128像素. bmp文件。SegmentByThreshold()函数将从灰度图像转换成黑白的,因为与我们的液晶像素上或者没有灰色的允许。一系列bitset()操作将该图像数据转换成像素数据,可以发送到EFM8和直接传输到液晶。注意,复杂的计算应用程序像Scilab并不完全适合我们使用的那种尴尬的逐位运算。换句话说,双层循环在上面的代码块执行需要很长时间(例如,大约23秒2.5 GHz处理器运行Windows 8.1)。因此,如果你想要适应这个代码显示一个动画序列,您需要将所有的图像转换为液晶像素格式EFM8在你开始发送数据。

Scilab脚本的另一个主要部分的for循环,将像素数据发送到EFM8通过VCP连接:

四行像素数据转换为一维数组和传播作为一个64字节的数据包使用slSendArray()函数。然后脚本读取单确认发送字节从EFM8之前,在接下来的四行像素数据。重要提示:调用slReadByte()在这个脚本中对第二个参数“1”,即。、响应= slReadByte (EFM8Port,1)。这个“1”表示函数,也就是说Scilab将什么都不做,直到至少有一个字节的到来。这里的优势在于,尽可能快地运行脚本,因为执行将继续尽快EFM8字节发送确认。不过,问题是,如果出现错误和字节永远不会到来,Scilab将昏迷直到你关闭程序和重启它。因此,在调试阶段一个更好的方法是使用睡眠()函数给EFM8反应时间然后读取字节没有屏蔽,即。slReadByte (EFM8Port0)。

Scilab脚本也称抽搐()和toc()来测量和显示的时间需要传输和显示一个图像。相同的2.5 GHz Windows机器上面所提到的,这个过程只需要大约50 ms,这意味着这个系统应该能够轻松地维持一个动画每秒10图像的帧率。

USB_Image_to_EFM8.zip

自己尝试这个项目!BOM。