当前位置:首页 > 嵌入式 > 嵌入式软件
[导读]WINCE6.0 简单LED驱动程序的编写

把它写成了实验报告的样子! 在此BLOG中的有些函数是针对特定的BSP, 比如:地址的映射函数, 在每一个BSP中它的地址映射函数都不同, 但是都是地址映射(废话当然是地址映射了)。其实里面有很多的东西都还可以添加:比如添加读取LED信息状态, 优化地址映射(不必把全部的GPIO都映射, 可以自定义一个小的结构体来实现)。
一. 实验目的
a) 掌握流驱动的结构
b) 掌握一般流驱动的编写方法

二. 实验设备
a) S3C6410 开发板一台
b) PC 机一台, VS2005, CE6.0 环境

三. 实验内容
a) 进行简单 LED 驱动的编写。

四. 实验原理
a) 硬件原理图
i.
ii.
iii. 从原理图可以知道如果我们要点亮 LEDx , 只需要 GPMx 输出高电平, 如果要熄灭 LEDx , 只需要 GPMx 输出低电平即可。

b) 软件原理设计
i. 由于在 WINCE 中使用都是虚拟的地址, 所以需要将实际的物理地址转换为虚拟地址来使用。 在系统提供的 BSP 中提供了一个函数来实现从物理地址到虚拟地址的映射。
1. void *DrvLib_MapIoSpace (UINT32 PhysicalAddress , UINT32 NumberOfBytes , BOOL CacheEnable )
2. 把物理地址转换为虚拟地址。(其实它就是在地址映射表中查找相应的物理地址,然后返回对应的虚拟地址加上它的偏移。)
3. UINT32 PhysicalAddress :要实现映射的物理地址的起始地址。
4. UINT32 NumberOfBytes : 要映射物理地址的长度。
5. BOOL CacheEnable :该物理地址是否使用了CACHE.( 具体参照地址映射表) 。
ii. LED 上下文结构体的定义
1. 定义了一个 LED 驱动的上下文, 用来保存 LED 驱动的信息。 但是只是简单的 LED 驱动, 没有包含多的数据。
typedef struct
{
volatile S3C6410_GPIO_REG *pGPIOReg ;
}LED_PUBLIC_CONTEXT , *PLED_PUBLIC_CONTEXT ;
2 . S3C6410_GPIO_REG 是BSP 预先定义的一个GPIO 使用的数据结构。
iii. GPIO 寄存器的使用。 GPIO 寄存器的地址都映射到了虚拟的地址上。 BSP 提供了一个结构体方便 GPIO 寄存器的使用。
1. typedef struct
{ ……………..
UINT32 GPMCON; // 820
UINT32 GPMDAT; // 824
UINT32 GPMPUD; // 828
………………..
} S3C6410_GPIO_REG, *PS3C6410_GPIO_REG;
2. 在使用这个结构全的时候把 GPIO 的虚拟地址的基地址映射到此结构的开始即可以操作此结构体的数据来操作实际的寄存器。
3. 进行GPIO 物理地址到虚拟地址的映射: pLedContext ->pGPIOReg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace (S3C6410_BASE_REG_PA_GPIO , sizeof (S3C6410_GPIO_REG ), FALSE ) ;
iv. 实现 LED 灯状态的操作。
1. 获得了 GPIO 的虚拟地址就可以像实际的物理地址那样实现寄存器的操作。
2.
a) // 使能上拉
b) pLedContext ->pGPIOReg ->GPMPUD |= 0x0ff;
c) // 设置为输出
d) pLedContext ->pGPIOReg ->GPMCON = 0x111111;
e) // 关闭所有的LED
f) LED_ALL_OFF (pLedContext ->pGPIOReg ->GPMDAT );
3. 为了方便进行操作,定义了一组宏。
// 打开或关闭LED0
#define LED0_ON (x ) (x |= 0x00000001)
#define LED0_OFF (x ) (x &= 0xfffffffe)
// 打开或关闭LED1
#define LED1_ON (x ) (x |= 0x00000002)
#define LED1_OFF (x ) (x &= 0xfffffffd)
// 打开或关闭LED2
#define LED2_ON (x ) (x |= 0x00000004)
#define LED2_OFF (x ) (x &= 0xfffffffb)
// 打开或关闭LED3
#define LED3_ON (x ) (x |= 0x00000008)
#define LED3_OFF (x ) (x &= 0xfffffff7)
// 打开或关闭所有的LED
#define LED_ALL_ON (x ) (x |= 0x0000000f)
#define LED_ALL_OFF (x ) (x &= 0xfffffff0)
五. 实验步骤
a) Xxx_Init 函数的原型:
i. DWORD XXX_Init( LPCTSTR pContext , DWORD dwBusContext );
ii. pContext: Pointer to a string containing the registry path to the active key for the stream interface driver.
iii. lpvBusContext: Potentially process-mapped pointer passed as the fourth parameter to ActivateDeviceEx . If this driver was loaded through legacy mechanisms, then dwBusContext is zero. This pointer, if used, has only been mapped again as it passes through the protected server library (PSL). The XXX _Init function is responsible for performing all protection checking
iv. 返回值 : Returns a handle to the device context created if successful. Returns zero if not successful. This handle is passed to the XXX_Open (Device Manager) , XXX_PowerDown (Device Manager) , XXX_PowerUp (Device Manager) , and XXX_Deinit (Device Manager) functions
v. 注意:当调用 设备管理程序当调用 ActivateDeviceEx 函数的时候会间接调用到此函数, ActivateDeviceEx 的作用就是加载设备
vi. LED_Init 函数的编写。 LED_Init 最主要的功能就是进行硬件的初使化。
vii. LED_Init 函数的实现:
DWORD Led_Init (LPCTSTR pContext )
{
volatile PLED_PUBLIC_CONTEXT pLedContext ;

RETAILMSG (DEBUG_LED ,(TEXT ("Led_Init Function!/n" )));

// 申请LED 的CONTEXT
pLedContext = (PLED_PUBLIC_CONTEXT )LocalAlloc (LPTR , sizeof (pContext ));
if (!pLedContext )
{
RETAILMSG (DEBUG_LED , (TEXT ("Can't alloc memory for led context!/n" )));
return NULL ;
}

// 得到GPIO 寄存器的地址
pLedContext ->pGPIOReg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace (S3C6410_BASE_REG_PA_GPIO , sizeof (S3C6410_GPIO_REG ), FALSE );
if (pLedContext ->pGPIOReg == NULL )
{
RETAILMSG (DEBUG_LED , (TEXT ("LED for pGPIORges: DrvLib_MapIoSpace failed!/n" )));
LocalFree (pLedContext );
return NULL ;
}

// 使能上拉
pLedContext ->pGPIOReg ->GPMPUD |= 0x0ff;
// 设置为输出
pLedContext ->pGPIOReg ->GPMCON = 0x111111;
// 关闭所有的LED
LED_ALL_OFF (pLedContext ->pGPIOReg ->GPMDAT );
RETAILMSG (DEBUG_LED , (TEXT ("Led0 on! %d!/n" ), (pLedContext ->pGPIOReg ->GPMDAT )));

return pLedContext ;
` }
a) Xxx_Write 函数原型:
DWORD XXX_Write(DWORD
hOpenContext
, LPCVOID
pBuffer
, DWORD
Count
);


i. hOpenContext : Handle to the open context of the device. The call to the XXX_Open (Device Manager) function returns this identifier 。
ii. pBuffer : Pointer to the buffer that contains the data to write.
iii. Count: Number of bytes to write from the pBuffer buffer into the device.
iv. 返回值: The number of bytes written indicates success. A value of –1 indicates failure.
v. LED_Write 函数的作用只是进行对 LED 状态的写入。
自定义结构体:
typedef struct
{
unsigned char cLedNum ;
unsigned char fLedStatue ;
}LED_DATA , *PLED_DATA ;
cLedNum :LED 的标号。0 对应第一个LED, 1 对应第2 个LED … 4 表示全部熄灭(因为它只有4 个LED )
fLegStatue :将要实现的操作。 0 熄灭, 1 点亮。
vi. LED_Write 函数的实现。
DWORD Led_Write (DWORD hOpenContext ,
DWORD pBuffer ,
DWORD Count )
{
PLED_DATA pLedData = (PLED_DATA )pBuffer ;
RETAILMSG (DEBUG_LED , (TEXT ("Current hOpenContext %d /n" )), hOpenContext );
RETAILMSG (DEBUG_LED , (TEXT ("Corrent GPMDATA %d!/n" ), (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT )));

switch (pLedData ->cLedNum )
{
case 0:
if (pLedData ->fLedStatue )
{
LED0_ON (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
RETAILMSG (DEBUG_LED , (TEXT ("Led0 on! %d/n!" ), ((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT ));
}
else
{
LED0_OFF (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
RETAILMSG (DEBUG_LED , (TEXT ("Led0 off!/n!" )));
}
break ;
case 1:
。。。。。。
break ;
case 2:
。。。。。。
break ;
case 3:
。。。。。。
case 4:
if (pLedData ->fLedStatue )
{ LED_ALL_ON (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
}
else
{ LED_ALL_OFF (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
}
default :
break ;
}

return (Count );
}

b) 其它流接口函数的编写:其它的流接口函数并没有实现函数过程, 它们一般就直接返回。在Led_Deinit 函数中进行了申请内存的释放,也调用了一个放弃映射的函数DrvLib_UnmapIoSpace , 其实这个函数在6.0 之中没有作用, 它是直接返回结果的函数。
c) LED 的配置:
设备管理器要使用LED 流驱动的接口,就必须将LED 提供的接口函数导出。在Led.def 文件中添加如下代码:
LIBRARY LED

EXPORTS Led_Init
Led_Deinit
Led_Open
Led_Close
Led_Read
Led_Write
Led_Seek
Led_PowerDown
Led_PowerUp
Led_IOControl

导出了LED 的接口函数,要把Led.dll 添加到镜像文件中去还要修改platform.bib 文件。

在 MODULES 节中添加代码如图:


最后修改注册表 platform.reg :
HKEY_LOCAL_MACHINE/Drives/BuildIn 下添加注册表项 LED( 任意名字都可 )
注册表项中的内容:

六. 实验结果及分析
a) 按照上述步骤进行 LED 流驱动的编写, 再编写一个简单的应用程序即可进行 LED 灯的控制。

 

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动是为LED提供稳定电流及保护的半导体电源设备,属于高效能电子转换装置,主要应用于照明、显示屏背光及便携式产品等领域。

关键字: LED驱动

在一些应用中,希望在某些情况下可调节灯光的亮度,以便进一步节能和提供舒适的照明。

关键字: LED驱动

LED凭借其高效节能、长寿命、环保等诸多优势,已成为照明市场的主流选择。而LED驱动器作为LED照明系统的核心部件,其性能直接影响着LED灯具的稳定性和可靠性。然而,在LED驱动器设计过程中,电磁兼容性(EMC)问题一直...

关键字: LED驱动 EMC

北京2025年2月28日 /美通社/ -- 日前,《服务器操作系统迁移指南》(以下简称《指南》)经中国电子工业标准化技术协会批准后正式发布,将于3月正式实施。《指南》由浪潮信息牵头,中国电子技术标准化研究院、阿里云、统信...

关键字: 操作系统 编写 CPU 内存

本文将演示一种加速嵌入式系统设计原型阶段的方法,说明如何将与硬件无关的驱动程序和传感器结合使用,简化整个嵌入式系统的器件选择。同时还将介绍嵌入式系统的器件、典型软件结构以及驱动程序的实现。后续文章“利用与硬件无关的方法简...

关键字: 嵌入式系统 驱动程序 传感器

多年来TI一直致力于为汽车行业用户提供最具竞争力的LED驱动解决方案,构建创新、可靠、经济高效的汽车照明系统。

关键字: 照明系统 LED驱动

随着科技的飞速发展,嵌入式系统已经成为现代生活不可或缺的一部分,它们被广泛应用于从智能家居到自动驾驶汽车的各个领域。而在这些系统中,C语言由于其高效性、可移植性和对硬件的直接控制能力,成为了嵌入式系统开发的首选语言。

关键字: C语言 驱动程序

北京2025年1月3日 /美通社/ -- 近日,人民日报海外网与中华环保联合会联合主办的第二届中国品牌形象海外传播论坛暨2024中国企业ESG蓝皮书发布会在北京举行。现场发布了《企业ESG蓝皮书:中国企业环境、社会与治理...

关键字: 可持续发展 WIND 智能化 编写

LED驱动IC是一种集成电路,它通过控制电流来驱动LED灯,这种IC具有许多优点,包括低功耗、高亮度、长寿命、环保等,随着LED驱动IC技术的进步,LED照明设备的成本也在不断降低,使得更多的应用场景得以实现。

关键字: LED LED驱动

每个嵌入式软件应用程序都必须在某个时候访问最低级别的固件并控制硬件。驱动程序的设计和实现对于确保系统能够满足其实时要求至关重要。

关键字: 嵌入式 驱动程序
关闭