下面针对流式程序:
流式程序主要是对IO口进行控制的。下面主要是对LED的控制。
在驱动程序里面有个xxx_iocontrol()函数(xxx为驱动的名字),这个函数主要是对IO口的控制,
你要对IO口实现怎样的控制都可以在这里编写。比如:
BOOL LED_IOControl(DWORD hOpenContext, //XXX_Open返回给上层的那个句柄
DWORD dwCode, //IO操作码
PBYTE pBufIn, //传入的Buffer,每个IO操作码都会定义自已的Buffer结构
DWORD dwLenIn, //以字节记的大小
PBYTE pBufOut, //分别为传出的Buffer,及其以字节记的大小
DWORD dwLenOut,
PDWORD pdwActualOut)
{
switch(dwCode)
{
case IO_CTL_GPIO_1_ON:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT&~(0x1<<4);
break;
case IO_CTL_GPIO_2_ON:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT&~(0x1<<5);
break;
case IO_CTL_GPIO_3_ON:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT&~(0x1<<6);
break;
case IO_CTL_GPIO_4_ON:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT&~(0x1<<7);
break;
case IO_CTL_GPIO_ALL_ON:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT&~(0xF<<4);
break;
case IO_CTL_GPIO_1_OFF:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT|(0x1<<4);
break;
case IO_CTL_GPIO_2_OFF:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT|(0x1<<5);
break;
case IO_CTL_GPIO_3_OFF:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT|(0x1<<6);
break;
case IO_CTL_GPIO_4_OFF:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT|(0x1<<7);
break;
case IO_CTL_GPIO_ALL_OFF:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT|(0xF<<4);
break;
default:
break;
}
RETAILMSG(1,(TEXT("LED_Control:Ioctl code = 0x%x/r/n"), dwCode));
return TRUE;
}
调用它的是DeviceIoControl()在应用程序里面,实现对GPIO的控制(高低电平控制)
如:
void CFlowLEDDlg::OnLedOn()
{
// TODO: Add your control notification handler code here
BOOL ret;
ret=::DeviceIoControl(hFile,IO_CTL_GPIO_ALL_ON,NULL, 1,NULL,0,NULL,NULL);
if(ret!=TRUE)
{
MessageBox(_T("关闭LED失败!"));
MessageBox(_T("请打开GPIO驱动!"));
}
}
看到没IO_CTL_GPIO_ALL_ON与LED_IOControl()语句是不是对应呢,当你按下该建后,
就会执行LED_IOControl()中的:
case IO_CTL_GPIO_1_ON:
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT&~(0x1<<4);
break;
也就灯亮。
解析:ret=::DeviceIoControl(hFile,IO_CTL_GPIO_ALL_ON,NULL, 1,NULL,0,NULL,NULL);
ret定义的是一个bool值,::是作用域标识符,它的意思是调用的全局函数。调用的系统的API
从当前窗口中得到该改窗口的值。
当然在试验之前我们需要打开驱动,像上面一样,在底层驱动里面的函数为:
DWORD LED_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT|(0xF<<4); //这里是打开gpio的:5 6 7 8
RETAILMSG(1,(TEXT("LED_Control: LED_Open/r/n")));
return TRUE;
}
同样在应用程序里面调用的是:CreateFile()函数来打开该驱动。
void CFlowLEDDlg::OnOpenGpio()
{
// TODO: Add your control notification handler code here
hFile=CreateFile(TEXT("LED0:"),GENERIC_READ | GENERIC_WRITE,0, NULL,OPEN_EXISTING,0,0);
//若打开怎返回一个不为INVALID_HANDLE_VALUE的句柄。
if(hFile==INVALID_HANDLE_VALUE)
{
MessageBox(_T("打开GPIO驱动失败!"));
}
else
{
MessageBox(_T("打开GPIO驱动成功!"));
}
}
其中:
“LED0:”中的表示设备好“0”是必需的,不管你的设备当中是不是刚好只有一个,不然的话
会出现打开不了这个设备的情况。
当用户程序调用CreateFile打开这个设备时,设备管理器就会调用此驱动程序的XXX_Open函数
同理:有打开驱动必然有关闭驱动,
在底层驱动里面的函数为:
BOOL LED_Close(DWORD hOpenContext)
{
v_pIOPregs->GPFDAT=v_pIOPregs->GPFDAT&(0xF<<4);
RETAILMSG(1,(TEXT("LED_Control: LED_Close/r/n")));
return TRUE;
}
在应用程序里面对应的是:
void CFlowLEDDlg::OnCloseGpio()
{
// TODO: Add your control notification handler code here
if(hFile!=INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
MessageBox(_T("关闭GPIO驱动成功!"));
}
else
{
MessageBox(_T("关闭GPIO驱动失败!"));
}
}
总结:
用应用程序控制GPIO的时候,第一打开驱动,当我们按下打开驱动按键的时候,应用程序执行的
是CreateFile()函数,当CreateFile()打开设备管理器的时候,设备管理器就会调用XXX_Open()
函数打开此驱动程序
关闭驱动的时候可以直接调用CloseHandle关闭这个设备句柄时,LED_Close()函数就会被设备
管理器调用来关闭驱动。
当驱动打开后,就可以对GPIO进行操作了,当用户想叫那个LED亮的时候,按下此键,应用程序
执行DeviceIoControl()函数,通过其第二参数的返回值来调用底层驱动函数LED_IOControl()
函数。灯灭函数同理。
参考:http://blog.csdn.net/WINCE_MAN/archive/2010/06/06/5651181.aspx