国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

英創信息技術嵌入式系統設備驅動接口的C#編程

英創信息技術 ? 來源:英創信息技術 ? 作者:英創信息技術 ? 2020-01-15 11:29 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

英創ARM9系列嵌入式主板,均預裝了WinCE 5.0、WinCE 6.0操作系統,用戶可使用標準的C/C++C#進行應用程序的開發。英創的嵌入式板卡一大特色就是提供了豐富的通訊接口,并實現了相應的驅動程序,用戶只需直接調用相應的接口函數即可實現。

在使用C#進行應用程序開發時,由于C#無法使用C++的靜態庫函數,對于一些流式驅動設備,比如ISA,GPIO,WDT,CAN,SPI,IRQ等,沒有封裝好的庫函數可操作,如果希望控制它們,一種辦法是使用C編寫com組件,在com組件中調用英創提供的相應主板SDK包里的靜態庫函數;另一種方法是直接調用API函數來訪問設備驅動。

對于大多數的流式驅動設備,應用程序使用的一般過程:
1、通過CreatFile打開設備,獲得設備句柄。
2、使用ReadFile讀取數據,使用WriteFile發送數據,以及使用DeviceIoControl對設備驅動進行設置、讀寫等操作。
3、使用完畢,用CloseHandle關閉設備。

在一般情況下,設備的專用功能都是通過DeviceIoControl來實現的,因此如何通過C#編程來操作DeviceIoControl尤為重要。本文以英創ARM9嵌入式主板EM9170為例,介紹如何使用DeviceIoControl來操作主板的ISA接口進行讀寫。GPIO,WDT,CAN,SPI,IRQ等其他流式設備的操作請參看英創開發光盤內提供的相關例程。

1、DeviceIoControl函數的定義
在wince中核心庫為coredll.dll,相當于window的kernel32.dll和user32.dll。要調用核心庫,首先需要在代碼中添加引用:

using System.Runtime.InteropServices;

在c#中DeviceIoControl及CreatFiles,CloseHandle函數聲明,及相關變量定義方法如下(該寫法并不固定)。

[DllImport('coredll.dll', EntryPoint = 'CreateFile', CharSet = CharSet.Unicode)]
private static extern int CreateFile(String lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
int lpSecurityAttributes,
int dwCreationDisposition,
int dwFlagsAndAttributes,
int hTemplateFile);

[DllImport('coredll.dll', EntryPoint = 'CloseHandle')]
private static extern int CloseHandle(int hObject);

[DllImport('coredll.dll', EntryPoint = 'DeviceIoControl')]
private static extern bool DeviceIoControl(int hDevice,
uint dwIoControlCode,
byte[] lpInBuf,
uint nInBufSize,
byte[] lpOutBuf,
uint nOutBufSize,
ref uint lpBytesReturned,
uint lpOverlapped);

DeviceIoControl函數參數分析:

參數 定義
hDevice 設備句柄
Handle類型
c#中可以對應成int或uint或IntPtr
通過CreatFiles獲得
dwIoControlCode 驅動控制命令
DWORD類型
C#中可以對應成int或uint
不同設備該值定義不同,根據該參數lpInBuffer,nInBufSize,lpOutBuf,nOutBufSize參數定義也不同,在c中,該值的宏定義為
#define CTL_CODE(DeviceType, Function, Method, Access) (
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) )

根據DeviceType, Function, Method, Access轉換而來
在前面代碼中為英創嵌入式主板EM9170的ISA及GPIO的CTL_CODE值定義,比如GPIO輸出控制的CTL_CODE定義
private const uint GPIO_IOCTL_OUT_ENABLE = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | ( 3900<< 2) | (METHOD_BUFFERED);
更多的dwIoControlCode值定義和輸入輸出參數定義請參看英創相關例程
lpInBuffer 輸入BUFFER
LPVOID類型
C#中可以對應成byte[]或ref Struct等,也可以使用unsafe傳遞指針
應用程序傳遞給驅動的數據指針
一般用byte[]的通用性好些,對于需要傳遞結構體指針的地方,可以使用Marshal類的方法拷貝結構體到byte數組內,或者直接根據struct成員值修改byte數組的相應位
nInBufSize 輸入BUFFER長度
DWORD類型
如果DeviceIoControl操作無輸出BUFFER,一般lpInBuffer為null,nInBufSize為0
lpOutBuf 輸出BUFFER
LPVOID類型
nOutBufSize 輸入BUFFER長度
DWORD類型
lpBytesReturned 操作程序實際返回的字節數指針
LPDWORD類型
C#中一般對應為ref uint
lpOverlapped 重疊操作結構
沒有使用,定為uint傳0,或者IntPtr傳IntPtr.Zero

在C#調用外部dll時,可以用uint來對應DWORD,用ref uint來對應LPDWORD,用IntPtr來對應各種指針,更通用的,可以直接使用byte[]來對應各種指針。

2、DeviceIoControl函數的操作實例
以英創嵌入式主板EM9170的ISA操作為例,以下代碼包括了CreatFile需要的參數定義,ISA操作的IOCTL定義,和ISA的DeviceIoControl操作傳入參數結構體的定義,和封裝DeviceIoControl的兩個ISA函數定義。

主函數操作程序打開ISA設備,并操作ISA輸出輸入,最后關閉設備。

private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const int OPEN_EXISTING = 3;
private const int FILE_FLAG_RANDOM_ACCESS = 0x10000000;
//------------------------bsp_drivers----------------------------------
//winioctl
private const uint FILE_DEVICE_BUS_EXTENDER = 0x0000002a;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
// ISA IO Control Codes
private const uint ISA_IOCTL_READ_WRITE = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3910 << 2) | (METHOD_BUFFERED);
private const uint ISA_IOCTL_BUS_RESET = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3911 << 2) | (METHOD_BUFFERED);
//------------------------bsp_drivers_end------------------------------
[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct ISA_BUS_ACCESS
{
[FieldOffset(0)]public uint dwCmd; // = 0: Read, = 1: Write
[FieldOffset(4)]public uint dwSeg; // = 0: ISA_CS0, = 1: ISA_CS1
[FieldOffset(8)]public uint dwOffset;
[FieldOffset(12)]public uint dwValue; // only lower byte valid
}
public static int OpenISA_DIO(String DevName)
{
int handle;
handle = CreateFile(DevName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, // sharing mode
0, // security attributes (ignored)
OPEN_EXISTING, // creation disposition
FILE_FLAG_RANDOM_ACCESS, // flags/attributes
0);
return handle;
}
public static bool CloseISA_DIO(int hISA_DIO)
{
if (hISA_DIO != 0)
{
if (CloseHandle(hISA_DIO) != 0)
{
return false;
}
}
return true;
}
public static bool ISA_Read(int hISA_DIO, int nSeg, uint nOffset, ref byte pRdValue)
{
ISA_BUS_ACCESS isabus;
uint lpBytesReturned = 0;
isabus.dwCmd = 0;
isabus.dwSeg = (uint)nSeg;
isabus.dwOffset = nOffset;
isabus.dwValue = 0;
int size = Marshal.SizeOf(typeof(ISA_BUS_ACCESS));
byte[] lpIntBuf = new byte[size];
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(isabus, buffer, false);
Marshal.Copy(buffer, lpIntBuf, 0, size);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
byte[] lpOutBuf = new byte[sizeof(byte)];
if (!DeviceIoControl(hISA_DIO, // file handle to the driver
ISA_IOCTL_READ_WRITE, // I/O control code
lpIntBuf, // in buffer
(uint)size, // in buffer size
lpOutBuf, // out buffer
sizeof(byte), // out buffer size
ref lpBytesReturned, // pointer to number of bytes returned
0)) // ignored (=NULL)
{
return false;
}
pRdValue = lpOutBuf[0];
return true;
}
public static bool ISA_Write(int hISA_DIO, int nSeg, uint nOffset, byte ucWrValue)
{
ISA_BUS_ACCESS isabus;
uint lpBytesReturned = 0;
isabus.dwCmd = 1;
isabus.dwSeg = (uint)nSeg;
isabus.dwOffset = nOffset;
isabus.dwValue = (uint)ucWrValue;
int size = Marshal.SizeOf(typeof(ISA_BUS_ACCESS));
byte[] lpIntBuf = new byte[size];
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(isabus, buffer, false);
Marshal.Copy(buffer, lpIntBuf, 0, size);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
if (!DeviceIoControl(hISA_DIO, // file handle to the driver
ISA_IOCTL_READ_WRITE, // I/O control code
lpIntBuf, // in buffer
(uint)size, // in buffer size
null, // out buffer
0, // out buffer size
ref lpBytesReturned, // pointer to number of bytes returned
0)) // ignored (=NULL)
{
return false;
}
return true;
}
static void Main(string[] args)
{
const int ISA_CS1 = 1;
int hISA;
hISA = OpenISA_DIO('ISA1:');
if( hISA == -1 )
{
Console.Write('Open ISA_DIO device fail!');
return;
}
bRet = ISA_Write(hISA, ISA_CS1, 0, b);
bRet = ISA_Read(hISA, ISA_CS1, 0, ref b);
CloseISA_DIO(hISA);
return;
}

3、傳遞結構體的操作說明
該例程的ISA_Read,ISA_Write和函數中,DeviceIoControl的參數lpIntBuf需要傳遞一個結構體指針,關于結構體的操作需要按以下步驟。

所以首先需要定義一個和接口定義相同的結構體,在C#中定義與C接口的結構體需要使用StructLayout字段聲明結構體的大小,和對齊規則。

在每個成員前面用FieldOffset字段設定該成員在結構體中的偏移。

[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct ISA_BUS_ACCESS
{
[FieldOffset(0)]public uint dwCmd; // = 0: Read, = 1: Write
[FieldOffset(4)]public uint dwSeg; // = 0: ISA_CS0, = 1: ISA_CS1
[FieldOffset(8)]public uint dwOffset;
[FieldOffset(12)]public uint dwValue; // only lower byte valid
}

然后設定結構體各成員值,將結構體拷貝到byte[]中,在C#中將結構體拷貝到byte數組需要使用Marshal類。

首先計算結構體大小
int size = Marshal.SizeOf(typeof(ISA_BUS_ACCESS));

創建一個byte[]
byte[] lpIntBuf = new byte[size];

用AllocHGlobal申請一塊非托管空間,并獲得該空間的指針
IntPtr buffer = Marshal.AllocHGlobal(size);

然后用StructureToPtr將結構體拷貝到指針位置,再用Copy將指針位置數據拷貝到byte數組。因為之前申請了內存空間,使用try-finally確報用FreeHGlobal釋放空間

try
{
Marshal.StructureToPtr(isabus, buffer, false);
Marshal.Copy(buffer, lpIntBuf, 0, size);
}
finally
{
Marshal.FreeHGlobal(buffer);
}

以上操作包括空間申請與釋放,效率并不高,為提高效率,應當將結構體成員變量值直接賦值到byte數組相應位置,如:
ISA_BUS_ACCESS isabus;
isabus.dwCmd = 1;

修改為
lpIntBuf[3] = 1;

注意整數的低位在高地址。

4、英創EM9170其他使用DeviceIoControl操作的設備dwIoControlCode值定義


//------------------------bsp_drivers----------------------------------
//winioctl
private const uint FILE_DEVICE_BUS_EXTENDER = 0x0000002a;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
// GPIO IO Control Codes
private const uint GPIO_IOCTL_OUT_ENABLE = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | ( 3900<< 2) | (METHOD_BUFFERED);
private const uint GPIO_IOCTL_OUT_DISABLE = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3901 << 2) | (METHOD_BUFFERED);
private const uint GPIO_IOCTL_OUT_SET = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3902 << 2) | (METHOD_BUFFERED);
private const uint GPIO_IOCTL_OUT_CLEAR = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3903 << 2) | (METHOD_BUFFERED);
private const uint GPIO_IOCTL_PIN_STATE = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3904 << 2) | (METHOD_BUFFERED);
// ISA IO Control Codes
private const uint ISA_IOCTL_READ_WRITE = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3910 << 2) | (METHOD_BUFFERED);
private const uint ISA_IOCTL_BUS_RESET = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3911 << 2) | (METHOD_BUFFERED);
//private const uint ISA_IOCTL_REDA_CS1 = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3912 << 2) | (METHOD_BUFFERED);
//private const uint ISA_IOCTL_WRITE_CS1 = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3913 << 2) | (METHOD_BUFFERED);
// SPI IO Control Codes
private const uint CSPI_IOCTL_EXCHANGE = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3030 << 2) | (METHOD_BUFFERED);
// IRQ IO Control Codes
private const uint IOCTL_WAIT_FOR_IRQ = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3920 << 2) | (METHOD_BUFFERED);
private const uint IOCTL_SEND_EOI = (FILE_DEVICE_BUS_EXTENDER << 16) | (FILE_ANY_ACCESS << 14) | (3921 << 2) | (METHOD_BUFFERED);
//------------------------bsp_drivers_end------------------------------

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式主板
    +關注

    關注

    7

    文章

    6107

    瀏覽量

    37071
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    嵌入式驅動開發,需要掌握哪些技能?

    :掌握UART、SPI、I2C接口常見通信協議,以及如何開發和調試相應的通信代碼。 2、 編程技能扎實的編程基礎:嵌入式
    發表于 01-20 16:46

    什么是嵌入式應用開發?

    包括ARM7、ARM9、ARM11、PowerPC、MIPS等。這些處理器和編程語言的選擇取決于具體的硬件條件和開發需求?。 綜上所述,嵌入式應用開發是一個綜合性的技術領域,涉及硬件和軟件的緊密結合,廣泛應用于各種
    發表于 01-12 16:13

    arm嵌入式主板優缺點

    嵌入式主板是嵌入設備里面做控制、數據處理使用的CPU板 ,常見的有兩類,即基于X86的嵌入式主板和基于RISC的ARM 嵌入式主板。今天我
    發表于 01-08 07:08

    從小白到大牛:Linux嵌入式系統開發的完整指南

    使用 C 語言(嵌入式開發主力語言)、POSIX 標準接口(文件 IO、進程、線程、信號量)。推薦通過 “溫度采集系統”“串口通信工具”等小型項目練手,重點掌握多線程
    發表于 12-16 10:42

    嵌入式應掌握的幾種能力

    1. 編程語言 基本掌握嵌入式必備的編程語言。C語言為主,C++為輔。在資源有限的情況下,大多數嵌入式
    發表于 12-08 06:05

    ARM嵌入式這樣學

    工程師的的終點只有一個,就是真正的技術專家。 嵌入式技術大體上可分為編程語言,內核技術,操作系統
    發表于 12-04 07:48

    CW32嵌入式軟件開發的必備知識

    。 能夠進行操作系統的任務設計、任務管理等,以滿足特定應用的需求。 5 、硬件接口與外設 熟悉常用的硬件接口,如GPIO、串口、SPI、I2C等,并能編寫相應的
    發表于 11-28 07:48

    C語言在嵌入式開發中的應用

    語言可以確保實時系統中的任務能夠在規定的時間內完成,保證系統的穩定性和可靠性。 4、嵌入式網絡編程 隨著物聯網技術的飛速發展,
    發表于 11-21 08:09

    嵌入式和FPGA的區別

    開發中做出更明智的技術選擇。 基本概念解析 嵌入式系統(Embedded System)是一種專用計算機系統,通常包含微處理器/微控制器、存儲器和專用外圍
    發表于 11-19 06:55

    嵌入式需要掌握哪些核心技能?

    /網絡設備)、中斷底半部處理,適用于高端嵌入式設備。 企業需求:RTOS是60%崗位的核心要求,Linux開發需求隨項目復雜度增長。 4)通信協議與接口 基礎協議:UART、SPI、
    發表于 10-21 16:25

    入行嵌入式應該怎么準備?

    知識: 一、C/C++編程C/C++是嵌入式系統
    發表于 08-06 10:34

    嵌入式開發入門指南:從零開始學習嵌入式

    特定功能的計算機系統,廣泛應用于智能家居、工業控制、醫療設備、車載系統等領域。 2. 學習嵌入式開發的前置知識熟悉C語言
    發表于 05-15 09:29

    ElfBoard嵌入式教育科普|ADC接口全面解析

    當代信息技術體系中,嵌入式系統接口作為數據交互的核心基礎設施,構成了設備互聯的神經中樞。基于標準化通信協議與
    的頭像 發表于 04-30 09:34 ?2288次閱讀
    ElfBoard<b class='flag-5'>嵌入式</b>教育科普|ADC<b class='flag-5'>接口</b>全面解析

    嵌入式編程設計模式

    嵌入式編程設計模式,介紹如何使用設計模式為嵌入式系統創建高效且優化的C語言設計。 純分享貼,有需要可以直接下載附件獲取完整資料! (如
    發表于 04-15 14:47

    如何成為一名嵌入式軟件工程師?

    體系 1)編程語言與工具 C/C++:嵌入式軟件開發中最常用的編程語言,因其高效性和對硬件的直接控制能力而備受青睞。 RTOS(實時操
    發表于 04-15 14:37