wince 控制 数码管 显示系统时间 控制流水灯
来源:互联网 发布:淘宝更改所在地 编辑:程序博客网 时间:2024/05/01 06:06
先看几个函数
:
BOOL VirtualCopy(
LPVOID lpvDest, // 虚拟内存的目标地址
LPVOID lpvSrc, // 物理内存地址
DWORD cbSize, // 要绑定的大小
DWORD fdwProtect // 访问权限
VirtualAlloc()函数用于分配一块内存空间。如果要映射一硬件寄存器,必然要将其映射到一块确定的内存空间。
LPVOID VirtualAlloc(
LPVOID lpAddress, // 希望的虚拟内存起始地址
DWORD dwSize, // 以字节为单位的大小
DWORD flAllocationType, // 申请类型,Reserve和Commit
DWORD flProtect // 访问权限
);
例: VirtualAlloc(0,0x1000,MEM_RESERVE,PAGE_READWRITE)
VirtualCopy((PVOID)pLightReg,(PVOID)(pLightIoBaseAddress>>8),0x1000,PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL)
这里的pLightReg即前面分配的虚拟地址空间,而pLightIoBaseAddress为实际的硬件地址,需要将它右移8位,因为在函数中存储器分配是以256位为单位的。而后面的选项则指定了映射地址的属性——可读写、不缓冲以及硬件物理地址。
extern "C" __declspec(dllimport) BOOL VirtualCopy(LPVOID lpvDest, LPVOID lpvSrc, DWORD cbSize, DWORD fdwProtect );
释放虚拟空间
BOOL VirtualFree(
LPVOID lpAddress, // 虚拟内存的地址
DWORD dwSize, // 释放的地址空间区域的大小
DWORD dwFreeType // 释放内存类型
);
如果参数dwFreeType指定了MEM_RELEASE标志,则将dwSize设置为0,由系统计算在特定内存地址上的待释放区域的大小。
VirtualFree((PVOID) pLightReg,0,MEM_RELEASE);
释放虚拟空间
BOOL VirtualFree(
LPVOID lpAddress, // 虚拟内存的地址
DWORD dwSize, // 释放的地址空间区域的大小
DWORD dwFreeType // 释放内存类型
);
如果参数dwFreeType指定了MEM_RELEASE标志,则将dwSize设置为0,由系统计算在特定内存地址上的待释放区域的大小。
VirtualFree((PVOID) pLightReg,0,MEM_RELEASE);
我们通过VirtualAlloc得到所分配的空间的首地址,通过VirtualCopy函数使得物理内存和虚拟内存进行绑定,这时我们通过返回的地址空间的首地址,就可以对物理地址进行读写,即控制小灯的状态。
假设pLightReg为虚拟空间首地址,当我们作如下操作时
*pLightReg = 0X7e;
小灯的状态相应发生变化。* pLightReg的每一位控制一个小灯的状态,* pLightReg从低位到高位依次控制H1~H8,并且低电平有效。
此时* pLightReg = (0111 1110)B,所以只有H1和H8被点亮。
1控制数码管显示系统时间
在本实验箱中七段数码管是共阳极的,所以每一段是由低电平触发。数码管的a~g段的状态对应着控制数据低位到高位的电平,且数据位的最高位为七段数码管的选通位,当其为0时,七段数码管才工作。
例 dp g f e d b c b a
0 0 0 0 0 0 0 1 0
*v_pLEDBaseAddr1 = 0X02 时,
七段数码管如右图显示
和小灯不同的是,八个小灯的状态由一个字节的数据控制,
而八个字节的数据只能控制一个7段数码管。
LED_CS2 = 0x10300000和LED_CS3 = 0x10400000分别控制两个7段数码管,所以控制数码管时,注意自定义变量的类型和个数。
说的够多了:看代码:
#include <Windows.h>
WORD *pLightReg1 = NULL;//于物理内存相对应的虚拟内存地址的指针
WORD *pLightReg2 = NULL;
#define pLightIoBaseAddress1 0x10300000
#define pLightIoBaseAddress2 0x10400000
#define m_ShiftTime 1000
const int led[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//大家可以自己算一下 各个数字对应的数码管的代码值
extern "C" __declspec(dllimport) BOOL VirtualCopy(LPVOID lpvDest, LPVOID lpvSrc, DWORD cbSize, DWORD fdwProtect );
BOOL alloc();
DWORD WINAPI sevenlight(LPVOID lpParameter);//对下面用到的函数进行先声明
int _tmain(int argc, _TCHAR* argv[])//主函数
{
HANDLE h;
if(alloc())
{
h= (HANDLE)::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(sevenlight),NULL,0,NULL);//创建一个以sevenlight为入口函数的主函数
::WaitForSingleObject(h,INFINITE);//等待线程结束 这行代码很关键 第一次就是因为没有写这个代码怎么也出不来,如果不等待线程结束二十直接CLOSEHANDLE大家可以想一下后果 那必须是直接结束没商量啊
::CloseHandle(h);
}
return 0;
}
BOOL alloc()
{
pLightReg1=(WORD*)VirtualAlloc(0,0x100,MEM_RESERVE,PAGE_READWRITE);//在本机上开辟一块内存
pLightReg2=(WORD*)VirtualAlloc(0,0x100,MEM_RESERVE,PAGE_READWRITE);
if(!pLightReg1 || !pLightReg2)
return FALSE;
if(!VirtualCopy((PVOID)pLightReg1,(PVOID)(pLightIoBaseAddress1>>8),0x100,PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL))//把对应的物理地址和当前本机上分配的地址进行绑定 这样对本机分配地址的指针进行操作就可以控制 物理机上的设备
{
VirtualFree((PVOID)pLightReg1,0,MEM_RELEASE);
pLightReg1 = NULL;
return FALSE;
}
if(!VirtualCopy((PVOID)pLightReg2,(PVOID)(pLightIoBaseAddress2>>8),0x100,PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL))
{
VirtualFree((PVOID)pLightReg2,0,MEM_RELEASE);
pLightReg2 = NULL;
return FALSE;
}
return TRUE;
}
DWORD WINAPI sevenlight(LPVOID lpParameter)
{
WORD tmp1;
WORD tmp2;
while(1){
SYSTEMTIME time;
::GetLocalTime(&time);
int a,b;
a = time.wSecond%10;
b = (time.wSecond-a)/10;
tmp1=led[b];
tmp2=led[a];
*pLightReg2=(tmp2<<8)+tmp1;//这一步很关键 大家想想为什么 WOED是16位的 它控制的是两个八位的数码管 所以要是控制这个数码管显示出两个十进制数 可以这样做 先声明两个16进制数 都赋给两个八位的数 然后让一个往右移八位加上另一个 补上空位 这样不就实现了么
a = time.wMinute%10;
b = (time.wMinute-a)/10;
tmp1=led[b];
tmp2=led[a];
*pLightReg1=(tmp2<<8)+tmp1;
Sleep(1000);
}
return 0;
}
控制流水灯
// demo1.cpp : 定义控制台应用程序的入口点。
//
#include <Windows.h>
#include "stdafx.h"
char *pLightReg = NULL;
#define pLightIoBaseAddress 0x10500000
#define m_ShiftTime 500
CRITICAL_SECTION g_cs;
extern "C" __declspec(dllimport) BOOL VirtualCopy(LPVOID lpvDest, LPVOID lpvSrc, DWORD cbSize, DWORD fdwProtect );
BOOL alloc();
DWORD WINAPI LeftShift(LPVOID lpParameter);
DWORD WINAPI RightShift(LPVOID lpParameter);
DWORD WINAPI MidShift(LPVOID lpParameter);
DWORD WINAPI LoopShift(LPVOID lpParameter);
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE h[2];
if(alloc())
{
::InitializeCriticalSection(&g_cs);
h[0] = (HANDLE)::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(LeftShift),NULL,0,NULL);
h[1] = (HANDLE)::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(RightShift),NULL,0,NULL);
::WaitForSingleObject( h[0], INFINITE );
::WaitForSingleObject( h[1], INFINITE );
::CloseHandle(h[0]);
::CloseHandle(h[1]);
::DeleteCriticalSection(&g_cs);
}
return 0;
}
BOOL alloc()
{
pLightReg=(char*)VirtualAlloc(0,0x100,MEM_RESERVE,PAGE_READWRITE);
if(!pLightReg)
return FALSE;
if(!VirtualCopy((PVOID)pLightReg,(PVOID)(pLightIoBaseAddress>>8),0x100,PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL))
{
VirtualFree((PVOID)pLightReg,0,MEM_RELEASE);
pLightReg = NULL;
return FALSE;
}
return TRUE;
}
DWORD WINAPI LeftShift(LPVOID lpParameter)
{
unsigned char tmp;
tmp=0x01;
while(1)
{
for(int i=0;i<8;i++)
{
::EnterCriticalSection(&g_cs);
*pLightReg=~tmp;
Sleep(m_ShiftTime);
tmp=tmp<<1;
::LeaveCriticalSection(&g_cs);
}
tmp=0x01;
}
return 0;
}
DWORD WINAPI RightShift(LPVOID lpParameter)
{
unsigned char tmp;
tmp=0x80;
while(1)
{
for(int i=0;i<8;i++)
{
::EnterCriticalSection(&g_cs);
*pLightReg=~tmp;
Sleep(m_ShiftTime);
tmp=tmp>>1;
::LeaveCriticalSection(&g_cs);
}
tmp=0x80;
}
return 0;
}
DWORD WINAPI MidShift(LPVOID lpParameter)
{
unsigned char tmp1;
unsigned char tmp2;
tmp1 = 0x01;
tmp2 = 0x80;
unsigned char tmp=tmp1|tmp2;
while(1)
{
for(int i=0;i<8;i++)
{
*pLightReg=~tmp;
Sleep(m_ShiftTime);
tmp1=tmp1<<1;
tmp2=tmp2>>1;
tmp=tmp1|tmp2;
}
tmp1 = 0x01;
tmp2 = 0x80;
tmp=tmp1|tmp2;
}
return 0;
}
DWORD WINAPI LoopShift(LPVOID lpParameter)
{
unsigned char tmp1;
unsigned char tmp2;
tmp1 = 0x01;
tmp2 = 0x80;
while(1)
{
for(int i=0;i<8;i++)
{
*pLightReg=~tmp1;
Sleep(m_ShiftTime);
tmp1=tmp1<<1;
}
for(int i=0;i<8;i++)
{
*pLightReg=~tmp2;
Sleep(m_ShiftTime);
tmp2=tmp2>>1;
}
tmp1 = 0x01;
tmp2 = 0x80;
}
return 0;
}
- wince 控制 数码管 显示系统时间 控制流水灯
- 单片机控制流水灯 数码管显示时间 蜂鸣器报警
- 按键控制数码管显示
- 按键控制数码管显示
- 单片机控制的数码管显示
- 定时器控制数码管扫描显示
- 按键控制单个数码管显示
- 定时器0控制LED的闪烁时间;计数器1来控制数码管的显示
- 开关控制流水灯
- 中断+数码管动态显示+流水灯
- 七段数码管显示控制 (4个数码管)
- 【数码管/定时器/中断】一个定时器控制数码管显示
- 外中断(按键)控制数码管显示
- 52单片机控制数码管显示数字
- 51单片机控制数码管拉幕显示
- 4×4矩阵键盘,控制数码管显示
- 用定时器1控制四位数码管从6432减到6393保持住这个数值,同时用定时器0控制流水灯从上至下以500ms移动同时停止!!!然后流水灯全部闪烁2.4秒后熄灭!继而数码管上显示6666
- WinCE显示系统时间
- android NDK 初步知识
- minicom
- Android游戏开发教程汇总
- Introduction to MSMQ
- 开公司的心得-租房子,得注意!
- wince 控制 数码管 显示系统时间 控制流水灯
- lpc2136的iap
- 初级日语语法整理
- matlab中调用c语言函数
- JS高级应用(一)
- Linux_Shell知多少—2—sed应用
- 怎样设计一个简洁的手机网站
- 开源3d引擎WildMagic4p7编译方法
- android布局配置