error LNK2019: unresolved external symbol “unsigned int (__stdcall* ATL::g_pfnGetThreadACP)(void)
又郁闷了很久,后来按datasheet和示波器现实的调了下,总算是能显示了,先贴代码,以后再说从中学到的,要注意的吧。
main.c
1: // [4/8/2011 uty]
2: #include <reg51.h>
3: #include <intrins.h>
4: #include "time.h"
5: #include "18b20.h"
6: //-----------------------------------------------------------------------------//
7: //此表为 LED 的字模, 共阴数码管 0-9 -
8: unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码控制
9: //此表为8个数码管位选控制, 共阴数码管 1-8个 -
10: unsigned char code dispbit[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F}; //位选控制 查表的方法控制
11: //-----------------------------------------------------------------------------//
12: void delay(unsigned int i)
13: {
14: char j;
15: for(i; i > 0; i--)
16: for(j = 200; j > 0; j--);
17: }
18: //-----------------------------------------------------------------------------//
19: void InterruptInit()
20: {
21: TMOD|= 0x11;
22: TH1 = 0xD8; //10
23: TL1 = 0xF0;
24: IE = 0x8A;
25: TR1 = 1;
26: }
27: //-----------------------------------------------------------------------------//
28: void DisplayTemperature (unsigned int Temperature)
29: {
30: unsigned char temp = 0;
31: unsigned int NegativeTemperature = 0;
32:
33: // 4位数最前面的0不显示,bFront控制是否是最前面的0
34: unsigned char bFront = 1;
35:
36: temp = Temperature % 10000 / 1000;
37:
38: if (0 != temp)
39: {
40: // negative number
41:
42: NegativeTemperature = 0x1000 - Temperature;
43:
44: temp = NegativeTemperature % 10000 / 1000;
45: if (0 != temp || !bFront)
46: {
47: bFront = 0;
48: P3 = ~dispbit[0];
49: P2 = ~Disp_Tab[temp];
50: STC89_12M_DelayMs(5);
51: }
52: else
53: {
54: // display '-'
55: if (0 != (NegativeTemperature % 1000 / 100))
56: {
57: P3 = ~dispbit[0];
58: P2 = ~Disp_Tab[10]; //'-'
59: STC89_12M_DelayMs(5);
60: }
61: }
62:
63: temp = NegativeTemperature % 1000 / 100;
64: if (0 != temp || !bFront)
65: {
66: bFront = 0;
67: P3 = ~dispbit[1];
68: P2 = ~Disp_Tab[temp];
69: STC89_12M_DelayMs(5);
70: }
71: else
72: {
73: // display '-'
74: if (0 != (NegativeTemperature % 100 / 10))
75: {
76: P3 = ~dispbit[1];
77: P2 = ~Disp_Tab[10]; //'-'
78: STC89_12M_DelayMs(5);
79: }
80: }
81:
82:
83: temp = NegativeTemperature % 100 / 10;
84: if (0 != temp || !bFront)
85: {
86: bFront = 0;
87: P3 = ~dispbit[2];
88: P2 = ~Disp_Tab[temp];
89: STC89_12M_DelayMs(5);
90: }
91: else
92: {
93: // display '-'
94: if (0 != (NegativeTemperature % 10))
95: {
96: P3 = ~dispbit[2];
97: P2 = ~Disp_Tab[10]; //'-'
98: STC89_12M_DelayMs(5);
99: }
100: }
101:
102: temp = NegativeTemperature % 10;
103: P3 = ~dispbit[3];
104: P2 = ~Disp_Tab[temp];
105: STC89_12M_DelayMs(5);
106:
107: }
108: else
109: {
110: temp = Temperature % 10000 / 1000;
111: if (0 != temp || !bFront)
112: {
113: bFront = 0;
114: P3 = ~dispbit[0];
115: P2 = ~Disp_Tab[temp];
116: STC89_12M_DelayMs(5);
117: }
118:
119: temp = Temperature % 1000 / 100;
120: if (0 != temp || !bFront)
121: {
122: bFront = 0;
123: P3 = ~dispbit[1];
124: P2 = ~Disp_Tab[temp];
125: STC89_12M_DelayMs(5);
126: }
127:
128:
129: temp = Temperature % 100 / 10;
130: if (0 != temp || !bFront)
131: {
132: bFront = 0;
133: P3 = ~dispbit[2];
134: P2 = ~Disp_Tab[temp];
135: STC89_12M_DelayMs(5);
136: }
137:
138: // 如果温度是0 最后一位还是要显示
139: temp = Temperature % 10;
140: P3 = ~dispbit[3];
141: P2 = ~Disp_Tab[temp];
142: STC89_12M_DelayMs(5);
143: }
144: }
145: //-----------------------------------------------------------------------------//
146: void main (void)
147: {
148: unsigned int idata nCounter = 0;
149: unsigned int idata nTemperature = 0;
150:
151: nCounter = 10000;
152:
153: while (1)
154: {
155: if (nCounter >= 300)
156: {
157: nTemperature = GetTemperature ();
158: nCounter = 0;
159: }
160:
161: DisplayTemperature(nTemperature);
162:
163: nCounter++; ;
164: }
165: }
166: //-----------------------------------------------------------------------------//
ds18b20.c
1: // [4/29/2011 uty]
2: // 18b20 driver
3: #include <reg52.H>
4: #include <intrins.h>
5: #include "time.h"
6: #include "18b20.h"
7: //-----------------------------------------------------------------------------//
8: sbit D18B20=P1^7;
9: //-----------------------------------------------------------------------------//
10: unsigned char code CrcTable [256]={
11: 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
12: 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
13: 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
14: 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
15: 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
16: 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
17: 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
18: 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
19: 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
20: 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
21: 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
22: 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
23: 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
24: 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
25: 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
26: 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
27: //-----------------------------------------------------------------------------//
28: #define Delay1us _nop_
29: //-----------------------------------------------------------------------------//
30: void Delay480us ()
31: {
32: char i = 0;
33:
34: // 504 us
35: for (i = 0; i < 12; i++)
36: {
37: STC89_12M_Delay42us();
38: }
39: }
40: //-----------------------------------------------------------------------------//
41: void Delay240us ()
42: {
43: char i = 0;
44:
45: // 462 us
46: for (i = 0; i < 5; i++)
47: {
48: STC89_12M_Delay42us();
49: }
50:
51: STC89_12M_Delay10us();
52: STC89_12M_Delay10us();
53: STC89_12M_Delay10us();
54: }
55: //-----------------------------------------------------------------------------//
56: void Delay60us ()
57: {
58: STC89_12M_Delay10us();
59: STC89_12M_Delay10us();
60: STC89_12M_Delay10us();
61: STC89_12M_Delay10us();
62: STC89_12M_Delay10us();
63: STC89_12M_Delay10us();
64: }
65: //-----------------------------------------------------------------------------//
66: void Delay45us ()
67: {
68: STC89_12M_Delay10us();
69: STC89_12M_Delay10us();
70: STC89_12M_Delay10us();
71: STC89_12M_Delay10us();
72:
73: Delay1us();
74: Delay1us();
75: Delay1us();
76: Delay1us();
77: Delay1us();
78: }
79: //-----------------------------------------------------------------------------//
80: unsigned char reset(void)
81: {
82: unsigned char ch = 0;
83:
84: D18B20 = 1;
85: Delay1us();
86: D18B20 = 0; // 输入,外部上拉,等待18b20拉低
87: Delay480us();
88: D18B20 = 1; // 输入,外部上拉,等待18b20拉低
89:
90: Delay60us();
91:
92: ch = D18B20;
93:
94: Delay480us();
95:
96: D18B20 = 1;
97:
98: if (1 == ch)
99: {
100: return 0;
101: }
102: else
103: {
104: return 1;
105: }
106: }
107: //-----------------------------------------------------------------------------//
108: void write (unsigned char ch)
109: {
110: unsigned char i = 0;
111:
112: for (i = 0;i < 8; i++)
113: {
114: D18B20 = 0;
115: Delay1us();
116: Delay1us();
117: Delay1us();
118: Delay1us();
119: Delay1us();
120: Delay1us();
121: Delay1us();
122: Delay1us();
123: Delay1us();
124: Delay1us();
125: D18B20 = (ch & 0x01);
126: Delay45us();
127: Delay45us();
128: D18B20 = 1;
129: ch >>= 1;
130: }
131: }
132: //-----------------------------------------------------------------------------//
133: unsigned char read (void)
134: {
135: unsigned char i = 0;
136: unsigned char u = 0;
137:
138: for (i = 0; i < 8; i++)
139: {
140: u >>= 1;
141:
142: D18B20 = 1;
143: Delay1us();
144: Delay1us();
145: Delay1us();
146: D18B20 = 0;
147: Delay1us();
148: Delay1us();
149: D18B20 = 1;
150: Delay1us();
151: Delay1us();
152: Delay1us();
153: Delay1us();
154: if (1 == D18B20)
155: {
156: u |= 0x80;
157: }
158:
159:
160: D18B20 = 1;
161: Delay60us();
162: }
163:
164: return u;
165: }
166: //-----------------------------------------------------------------------------//
167: void read_bytes (unsigned char* buffer, unsigned char len)
168: {
169: unsigned char i = 0;
170:
171: for(i = 0; i < len; i++)
172: {
173: buffer[i] = read();
174: }
175: }
176: //-----------------------------------------------------------------------------//
177: unsigned char CRC (unsigned char* buff, unsigned char j)
178: {
179: unsigned char idata i,crc_data=0;
180: for(i=0;i<j;i++) //查表校验
181: crc_data = CrcTable[crc_data^buff[i]];
182: return (crc_data);
183: }
184: //-----------------------------------------------------------------------------//
185: unsigned int
186: ReadTemperature (void)
187: {
188: unsigned char ScratchpadBuffer[9] = {0};
189: unsigned int nTemperature = 0;
190:
191: read_bytes(ScratchpadBuffer, 9);
192: if (0 == CRC(ScratchpadBuffer, 9)) //校验正确
193: {
194: nTemperature = ScratchpadBuffer[1] * 0x100 + ScratchpadBuffer[0];
195: //nTemperature *= 0.625;
196: nTemperature /= 16;
197: }
198:
199: return nTemperature;
200: }
201: //-----------------------------------------------------------------------------//
202: unsigned int
203: GetTemperature (void)
204: {
205: unsigned int nTemperature = 0;
206: // 先取温度,然后再去转换温度,新转换的数据下次再取
207: reset ();
208: write(0xcc); //skip rom
209: write(0xbe); //read Temperature
210: nTemperature = ReadTemperature();
211:
212: reset ();
213: write(0xcc); //skip rom
214: write(0x44); //Temperature convert
215:
216: return nTemperature;
217: }
218:
219: /*************************************
220: [ t1 (10ms)中断] 中断
221: *************************************/
222: // void T1zd(void) interrupt 3
223: // {
224: // TH1 = 0xD8; //10
225: // TL1 = 0xF0;
226: // TIM++;
227: //
228: // }
229:
230: //-----------------------------------------------------------------------------//
231:
232: /************************************************************
233: *Function:内部配置
234: *parameter:
235: *Return:
236: *Modify:
237: *************************************************************/
238: // void Config18b20 (void) //重新配置报警限定值和分辨率
239: // {
240: // reset();
241: // write(0xcc); //skip rom
242: // write(0x4e); //write scratchpad
243: // write(0x19); //上限
244: // write(0x1a); //下限
245: // write(0x7f); //set 12 bit (0.125)
246: //
247: // reset();
248: // write(0xcc); //skip rom
249: // write(0x48); //保存设定值
250: // Init18b20();
251: // write(0xcc); //skip rom
252: // write(0xb8); //回调设定值
253: // }
254:
255: /************************************************************
256: *Function:读18B20ID
257: *parameter:
258: *Return:
259: *Modify:
260: *************************************************************/
261: // void ReadID (void)//读取器件 id
262: // {
263: // reset();
264: // write(0x33); //read rom
265: // read_bytes(8);
266: // }
time.c
1: // [4/19/2011 uty]
2: #include <intrins.h>
3: //-----------------------------------------------------------------------------//
4: void
5: STC89_12M_Delay1ms (void)
6: {
7: char i,j;
8: for(i = 110; i > 0; i--)
9: for(j = 200; j > 0; j--);
10: }
11: //-----------------------------------------------------------------------------//
12: //
13: // max 255 ms
14: //
15: void
16: STC89_12M_DelayMs (
17: unsigned char i
18: )
19: {
20: while (i--)
21: {
22: STC89_12M_Delay1ms();
23: }
24: }
25: //-----------------------------------------------------------------------------//
26: void STC89_12M_Delay10us ()
27: {
28: // LCALL指令(2 μs)
29:
30: _nop_( );
31: _nop_( );
32: _nop_( );
33: _nop_( );
34: _nop_( );
35: _nop_( );
36:
37: // RET指令(2 μs)
38: }
39: //-----------------------------------------------------------------------------//
40: void STC89_12M_Delay42us ()
41: {
42: STC89_12M_Delay10us();
43: STC89_12M_Delay10us();
44: STC89_12M_Delay10us();
45: STC89_12M_Delay10us();
46: }
47: //-----------------------------------------------------------------------------//
再上张图
AND 与门
ANTENNA 天线
BATTERY 直流电源
BELL 铃,钟
BVC 同轴电缆接插件
BRIDEG 1 整流桥(二极管)
BRIDEG 2 整流桥(集成块)
BUFFER 缓冲器
BUZZER 蜂鸣器
CAP 电容
CAPACITOR 电容
CAPACITOR POL 有极性电容
CAPVAR 可调电容
CIRCUIT BREAKER 熔断丝
COAX 同轴电缆
CON 插口
CRYSTAL 晶体整荡器
DB 并行插口
DIODE 二极管
DIODE SCHOTTKY 稳压二极管
DIODE VARACTOR 变容二极管
DPY_3-SEG 3段LED
DPY_7-SEG 7段LED
DPY_7-SEG_DP 7段LED(带小数点)
ELECTRO 电解电容
FUSE 熔断器
INDUCTOR 电感
INDUCTOR IRON 带铁芯电感
INDUCTOR3 可调电感
JFET N N沟道场效应管
JFET P P沟道场效应管
LAMP 灯泡
LAMP NEDN 起辉器
LED 发光二极管
METER 仪表
MICROPHONE 麦克风
MOSFET MOS管
MOTOR AC 交流电机
MOTOR SERVO 伺服电机
NAND 与非门
NOR 或非门
NOT 非门
NPN NPN三极管
NPN-PHOTO 感光三极管
OPAMP 运放
OR 或门
PHOTO 感光二极管
PNP 三极管
NPN DAR NPN三极管
PNP DAR PNP三极管
POT 滑线变阻器
PELAY-DPDT 双刀双掷继电器
RES1.2 电阻
RES3.4 可变电阻
RESISTOR BRIDGE ? 桥式电阻
RESPACK ? 电阻
SCR 晶闸管
PLUG ? 插头
PLUG AC FEMALE 三相交流插头
SOCKET ? 插座
SOURCE CURRENT 电流源
SOURCE VOLTAGE 电压源
SPEAKER 扬声器
SW ? 开关
SW-DPDY ? 双刀双掷开关
SW-SPST ? 单刀单掷开关
SW-PB 按钮
THERMISTOR 电热调节器
TRANS1 变压器
TRANS2 可调变压器
TRIAC ? 三端双向可控硅
TRIODE ? 三极真空管
VARISTOR 变阻器
ZENER ? 齐纳二极管
DPY_7-SEG_DP 数码管
SW-PB 开关
1: #include <REG52.H>
2: //-----------------------------------------------------------------------------//
3: void delay(unsigned int i)
4: {
5: unsigned char j;
6: for(i; i > 0; i--)
7: for(j = 200; j > 0; j--) ;
8: }
9: //-----------------------------------------------------------------------------//
10: void
11: InitSerial ()
12: {
13: SCON = 0x50;
14: TMOD |= 0x20;
15: PCON |= 0x80;
16: TH1 = 0xF3; // 晶振12.0 4800 baudrate
17: TL1 = 0xF3;
18: TR1 = 1;
19: ES = 1;
20: EA = 1;
21:
22: RI = 0;
23: TI = 0;
24: }
25: //-----------------------------------------------------------------------------//
26: void
27: SendByte (
28: unsigned char ch
29: )
30: {
31: TI = 0; // Be sure the bit is initially clear
32: SBUF = ch; // Send the letter A to the serial port
33: while (0 == TI); // Pause until the TI bit is set.
34: }
35: //-----------------------------------------------------------------------------//
36: void
37: SendString (
38: unsigned char* String
39: )
40: {
41: int i = 0;
42:
43: while ('' != String[i])
44: {
45: SendByte(String[i]);
46: i++;
47: }
48: }
49: //-----------------------------------------------------------------------------//
50: void main (void)
51: {
52: int a;
53:
54: InitSerial();
55:
56: while (1)
57: {
58: SendString("Hello world! ");
59: delay(100);
60: }
61: }
62: //-----------------------------------------------------------------------------//
本来很简单的一个小程序,但开始在用windows 超级终端接收的时候总是不成功,有时候能收到,但是断断续续的,每次连接只能收到几个字符,并且还总有一声咔的声音。后来发现是usb转串口的原因,可能是有bug吧,直接连外面的串口就一切正常了。
串口可以了,ISD51也就能用了,原来总不行的原因更郁闷,虽然#include <ISD51.h>,也把ISD51.A51和ISD51.h放到了工程目录下,但是忘了把ISD51.A51
加到工程里。。。结果编译器也没报错,我就当编进去了呢。用惯了vs哪怕vc6,用keil都不行了。。。。。 之后设置好baudrate就一切正常了。
超级终端接收的时候这样设置
数据流不需要硬件控制,停止位貌似1 1.5 2 都可以,因为baudrate比较低,所以数据之间空的非常多。
结果就是这样了
串口各寄存器的作用,有篇非常详细的介绍
8051 Tutorial: Serial Communication
One of the 8051s many powerful features is its integrated UART, otherwise known as a serial port. The fact that the 8051 has an integrated serial port means that you may very easily read and write values to the serial port. If it were not for the integrated serial port, writing a byte to a serial line would be a rather tedious process requring turning on and off one of the I/O lines in rapid succession to properly "clock out" each individual bit, including start bits, stop bits, and parity bits.
However, we do not have to do this. Instead, we simply need to configure the serial ports operation mode and baud rate. Once configured, all we have to do is write to an SFR to write a value to the serial port or read the same SFR to read a value from the serial port. The 8051 will automatically let us know when it has finished sending the character we wrote and will also let us know whenever it has received a byte so that we can process it. We do not have to worry about transmission at the bit level–which saves us quite a bit of coding and processing time.
The first thing we must do when using the 8051s integrated serial port is, obviously, configure it. This lets us tell the 8051 how many data bits we want, the baud rate we will be using, and how the baud rate will be determined.
First, lets present the "Serial Control" (SCON) SFR and define what each bit of the SFR represents:
Additionally, it is necessary to define the function of SM0 and SM1 by an additional table:
(*) Note: The baud rate indicated in this table is doubled if PCON.7 (SMOD) is set.
The SCON SFR allows us to configure the Serial Port. Thus, well go through each bit and review its function.
The first four bits (bits 4 through 7) are configuration bits.
Bits SM0 and SM1 let us set the serial mode to a value between 0 and 3, inclusive. The four modes are defined in the chart immediately above. As you can see, selecting the Serial Mode selects the mode of operation (8-bit/9-bit, UART or Shift Register) and also determines how the baud rate will be calculated. In modes 0 and 2 the baud rate is fixed based on the oscillators frequency. In modes 1 and 3 the baud rate is variable based on how often Timer 1 overflows. Well talk more about the various Serial Modes in a moment.
The next bit, SM2, is a flag for "Multiprocessor communication." Generally, whenever a byte has been received the 8051 will set the "RI" (Receive Interrupt) flag. This lets the program know that a byte has been received and that it needs to be processed. However, when SM2 is set the "RI" flag will only be triggered if the 9th bit received was a "1". That is to say, if SM2 is set and a byte is received whose 9th bit is clear, the RI flag will never be set. This can be useful in certain advanced serial applications. For now it is safe to say that you will almost always want to clear this bit so that the flag is set upon reception of any character.
The next bit, REN, is "Receiver Enable." This bit is very straightforward: If you want to receive data via the serial port, set this bit. You will almost always want to set this bit.
The last four bits (bits 0 through 3) are operational bits. They are used when actually sending and receiving data–they are not used to configure the serial port.
The TB8 bit is used in modes 2 and 3. In modes 2 and 3, a total of nine data bits are transmitted. The first 8 data bits are the 8 bits of the main value, and the ninth bit is taken from TB8. If TB8 is set and a value is written to the serial port, the datas bits will be written to the serial line followed by a "set" ninth bit. If TB8 is clear the ninth bit will be "clear."
The RB8 also operates in modes 2 and 3 and functions essentially the same way as TB8, but on the reception side. When a byte is received in modes 2 or 3, a total of nine bits are received. In this case, the first eight bits received are the data of the serial byte received and the value of the ninth bit received will be placed in RB8.
TI means "Transmit Interrupt." When a program writes a value to the serial port, a certain amount of time will pass before the individual bits of the byte are "clocked out" the serial port. If the program were to write another byte to the serial port before the first byte was completely output, the data being sent would be garbled. Thus, the 8051 lets the program know that it has "clocked out" the last byte by setting the TI bit. When the TI bit is set, the program may assume that the serial port is "free" and ready to send the next byte.
Finally, the RI bit means "Receive Interrupt." It funcions similarly to the "TI" bit, but it indicates that a byte has been received. That is to say, whenever the 8051 has received a complete byte it will trigger the RI bit to let the program know that it needs to read the value quickly, before another byte is read.
Setting the Serial Port Baud Rate
Once the Serial Port Mode has been configured, as explained above, the program must configure the serial ports baud rate. This only applies to Serial Port modes 1 and 3. The Baud Rate is determined based on the oscillators frequency when in mode 0 and 2. In mode 0, the baud rate is always the oscillator frequency divided by 12. This means if youre crystal is 11.059Mhz, mode 0 baud rate will always be 921,583 baud. In mode 2 the baud rate is always the oscillator frequency divided by 64, so a 11.059Mhz crystal speed will yield a baud rate of 172,797.
In modes 1 and 3, the baud rate is determined by how frequently timer 1 overflows. The more frequently timer 1 overflows, the higher the baud rate. There are many ways one can cause timer 1 to overflow at a rate that determines a baud rate, but the most common method is to put timer 1 in 8-bit auto-reload mode (timer mode 2) and set a reload value (TH1) that causes Timer 1 to overflow at a frequency appropriate to generate a baud rate.
To determine the value that must be placed in TH1 to generate a given baud rate, we may use the following equation (assuming PCON.7 is clear).
- TH1 = 256 – ((Crystal / 384) / Baud)
If PCON.7 is set then the baud rate is effectively doubled, thus the equation becomes:
- TH1 = 256 – ((Crystal / 192) / Baud)
For example, if we have an 11.059Mhz crystal and we want to configure the serial port to 19,200 baud we try plugging it in the first equation:
- TH1 = 256 – ((Crystal / 384) / Baud)
TH1 = 256 – ((11059000 / 384) / 19200 )
TH1 = 256 – ((28,799) / 19200)
TH1 = 256 – 1.5 = 254.5
As you can see, to obtain 19,200 baud on a 11.059Mhz crystal wed have to set TH1 to 254.5. If we set it to 254 we will have achieved 14,400 baud and if we set it to 255 we will have achieved 28,800 baud. Thus were stuck…
But not quite… to achieve 19,200 baud we simply need to set PCON.7 (SMOD). When we do this we double the baud rate and utilize the second equation mentioned above. Thus we have:
- TH1 = 256 – ((Crystal / 192) / Baud)
TH1 = 256 – ((11059000 / 192) / 19200)
TH1 = 256 – ((57699) / 19200)
TH1 = 256 – 3 = 253
Here we are able to calculate a nice, even TH1 value. Therefore, to obtain 19,200 baud with an 11.059MHz crystal we must:
- 1. Configure Serial Port mode 1 or 3.
2. Configure Timer 1 to timer mode 2 (8-bit auto-reload).
3. Set TH1 to 253 to reflect the correct frequency for 19,200 baud.
4. Set PCON.7 (SMOD) to double the baud rate.
Once the Serial Port has been propertly configured as explained above, the serial port is ready to be used to send data and receive data. If you thought that configuring the serial port was simple, using the serial port will be a breeze.
To write a byte to the serial port one must simply write the value to the SBUF (99h) SFR. For example, if you wanted to send the letter "A" to the serial port, it could be accomplished as easily as:
- MOV SBUF,#A
Upon execution of the above instruction the 8051 will begin transmitting the character via the serial port. Obviously transmission is not instantaneous–it takes a measureable amount of time to transmit. And since the 8051 does not have a serial output buffer we need to be sure that a character is completely transmitted before we try to transmit the next character.
The 8051 lets us know when it is done transmitting a character by setting the TI bit in SCON. When this bit is set we know that the last character has been transmitted and that we may send the next character, if any. Consider the following code segment:
- CLR TI ;Be sure the bit is initially clear
MOV SBUF,#A ;Send the letter A to the serial port
JNB TI,$ ;Pause until the TI bit is set.
The above three instructions will successfully transmit a character and wait for the TI bit to be set before continuing. The last instruction says "Jump if the TI bit is not set to $"–$, in most assemblers, means "the same address of the current instruction." Thus the 8051 will pause on the JNB instruction until the TI bit is set by the 8051 upon successful transmission of the character.
Reading data received by the serial port is equally easy. To read a byte from the serial port one just needs to read the value stored in the SBUF (99h) SFR after the 8051 has automatically set the RI flag in SCON.
For example, if your program wants to wait for a character to be received and subsequently read it into the Accumulator, the following code segment may be used:
- JNB RI,$ ;Wait for the 8051 to set the RI flag
MOV A,SBUF ;Read the character from the serial port
The first line of the above code segment waits for the 8051 to set the RI flag; again, the 8051 sets the RI flag automatically when it receives a character via the serial port. So as long as the bit is not set the program repeats the "JNB" instruction continuously.
Once the RI bit is set upon character reception the above condition automatically fails and program flow falls through to the "MOV" instruction which reads the value.
动NET_BUFFER还算行,动NET_BUFFER_LIST估计也可以,消耗就更大了。还有种方法就是换MDL,或者链在MdlChain后面, 然后改CurrentMdl,不过这种方法估计要自己维护个结构,看哪个Mdl是自己分配的,或者把相关的数据放到NET_BUFFER的MiniportReserved里,但原来的包在complete的时候要恢复的完全一样,想想还是替换NET_BUFFER最简单。
ndislwf可能还算较新的东西,网上相关的东西不多,希望这个例子能有帮助
晕 代码高亮的快疯了,就这样算了
1: VOID
2: FilterSendNetBufferListsComplete(
3: IN NDIS_HANDLE FilterModuleContext,
4: IN PNET_BUFFER_LIST NetBufferLists,
5: IN ULONG SendCompleteFlags
6: )
7: /*++
8:
9: Routine Description:
10:
11: SendNetBufferListComplete
12:
13: Arguments:
14:
15:
16:
17: Return Value:
18:
19: NONE
20:
21: --*/
22: {
23: PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
24: //ULONG NumOfSendCompletes = 0;
25: //BOOLEAN DispatchLevel;
26: //PNET_BUFFER_LIST CurrNbl;
27:
28: PNET_BUFFER_LIST pNetBufList = NULL;
29: PNET_BUFFER_LIST pNextNetBufList = NULL;
30:
31: PMDL pMdl = NULL;
32: PNDISPROT_ETH_HEADER pEthHeader = NULL;
33: ULONG ulOffset = 0;
34: ULONG ulBufferLength = 0;
35: PNET_BUFFER pCurrentNetBuffer = NULL;
36: PNET_BUFFER pPreviousNetBuffer = NULL;
37: PNET_BUFFER pOriginalNetBuffer = NULL;
38: ULONG ulTotalLength = 0;
39:
40: DEBUGP(DL_TRACE, ("===>SendNBLComplete, NetBufferList: %p.\n", NetBufferLists));
41:
42: //
43: // if necessary, undo any modifications to the NetBufferList thate were performed "on the way down"
44: //
45: //if (pFilter->TrackSends)
46: //{
47: // CurrNbl = NetBufferLists;
48: // while (CurrNbl)
49: // {
50: // NumOfSendCompletes++;
51: // CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
52: //
53: // }
54: // DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendCompleteFlags);
55: // FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
56: // pFilter->OutstandingSends -= NumOfSendCompletes;
57: // FILTER_LOG_SEND_REF(2, pFilter, PrevNbl, pFilter->OutstandingSends);
58: // FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
59: //}
60:
61:
62: pNetBufList = NetBufferLists;
63:
64: while (pNetBufList != NULL)
65: {
66: pNextNetBufList = NET_BUFFER_LIST_NEXT_NBL(pNetBufList);
67:
68: for (pCurrentNetBuffer = NET_BUFFER_LIST_FIRST_NB(pNetBufList);
69: pCurrentNetBuffer != NULL;
70: pCurrentNetBuffer = NET_BUFFER_NEXT_NB(pCurrentNetBuffer))
71: {
72: pMdl = NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer);
73: ulTotalLength = NET_BUFFER_DATA_LENGTH(pCurrentNetBuffer);
74: ulOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer);
75:
76: do
77: {
78: ASSERT(pMdl != NULL);
79: if (pMdl)
80: {
81: NdisQueryMdl(
82: pMdl,
83: &pEthHeader,
84: &ulBufferLength,
85: NormalPagePriority);
86: }
87: if (NULL == pEthHeader)
88: {
89: //
90: // The system is low on resources. Set up to handle failure
91: // below.
92: //
93: ulBufferLength = 0;
94: break;
95: }
96:
97: if (0 == ulBufferLength)
98: {
99: break;
100: }
101:
102: ASSERT(ulBufferLength > ulOffset);
103:
104: ulBufferLength -= ulOffset;
105: pEthHeader = (PNDISPROT_ETH_HEADER)((PUCHAR)pEthHeader + ulOffset);
106:
107: if (ulBufferLength < sizeof(NDISPROT_ETH_HEADER))
108: {
109: DEBUGP(DL_WARN,
110: ("ReceiveNetBufferList: runt nbl %p, first buffer length %d\n",
111: pNetBufList, ulBufferLength));
112:
113: break;
114: }
115:
116: //
117: // Check the EtherType. If the Ether type indicates presence of
118: // a tag, then the "real" Ether type is 4 bytes further down.
119: //
120: if (pEthHeader->EthType == NPROT_8021P_TAG_TYPE)
121: {
122: USHORT UNALIGNED *pEthType;
123:
124: if (ulBufferLength < (sizeof(NDISPROT_ETH_HEADER) + 4))
125: {
126: break;
127: }
128:
129: pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4);
130:
131: if (*pEthType != NPROT_ETH_TYPE)
132: {
133: break;
134: }
135: }
136: else if (pEthHeader->EthType != NPROT_ETH_TYPE)
137: {
138: break;
139: }
140:
141: //
142: // to do
143: //
144:
145: if (NdisGetPoolFromNetBuffer(pCurrentNetBuffer) == pFilter->NetBufferPool)
146: {
147: KdBreakPoint();
148:
149: pOriginalNetBuffer = NET_BUFFER_LIST_MINIPORT_RESERVED(pCurrentNetBuffer)[0];
150:
151: if (pCurrentNetBuffer == NET_BUFFER_LIST_FIRST_NB(pNetBufList))
152: {
153: NET_BUFFER_LIST_FIRST_NB(pNetBufList) = pOriginalNetBuffer;
154: }
155: else
156: {
157: pPreviousNetBuffer->Next = pOriginalNetBuffer;
158: }
159:
160: pOriginalNetBuffer->Next = pCurrentNetBuffer->Next;
161:
162:
163: NdisFreeNetBuffer(pCurrentNetBuffer);
164:
165: pCurrentNetBuffer = pOriginalNetBuffer;
166: }
167:
168: } while (FALSE);
169:
170: pPreviousNetBuffer = pCurrentNetBuffer;
171: }
172:
173:
174: pNetBufList = pNextNetBufList;
175: }
176:
177:
178:
179: NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, SendCompleteFlags);
180:
181: DEBUGP(DL_TRACE, ("<===SendNBLComplete.\n"));
182: }
1: VOID
2: FilterSendNetBufferLists(
3: IN NDIS_HANDLE FilterModuleContext,
4: IN PNET_BUFFER_LIST NetBufferLists,
5: IN NDIS_PORT_NUMBER PortNumber,
6: IN ULONG SendFlags
7: )
8: /*++
9:
10: Routine Description:
11:
12: Send Net Buffer List handler
13: This function is an optional function for filter drivers. If provided, NDIS
14: will call this function to transmit a linked list of NetBuffers, described by a
15: NetBuferList, over the network. If this handler is NULL, NDIS will skip calling
16: this fitler when sending a NetBufferList and will call the next lower fitler
17: in the stack with a non_NULL FilterSendNetBufferList handleror the miniport driver.
18: A filter that doesn't provide a FilerSendNetBufferList handler can not initiate a
19: send o its own.
20:
21: Arguments:
22:
23: FilterModuleContext: Pointer to our filter context area.
24: NetBufferLists: Pointer to a List of NetBufferLists.
25: PortNumber - Port Number to which this send is targetted
26: SendFlags- Specifies if the call is at DISPATCH_LEVEL
27:
28:
29: Return Value:
30:
31: NDIS_STATUS_SUCCESS:
32: NDIS_STATUS_PENDING:
33: NDIS_STATUS_INVALID_PACKET:
34: NDIS_STATUS_RESOURCES:
35: NDIS_STATUS_FAILURE:
36:
37:
38: NOTE: The filter will act like a passthru filter.
39:
40: --*/
41: {
42: NDIS_STATUS Status = NDIS_STATUS_FAILURE;
43: PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
44: //PNET_BUFFER_LIST CurrNbl;
45: //BOOLEAN DispatchLevel;
46: //BOOLEAN bFalse = FALSE;
47:
48: PNET_BUFFER_LIST pNetBufList = NULL;
49: PNET_BUFFER_LIST pNextNetBufList = NULL;
50:
51: PMDL pMdl = NULL;
52: PNDISPROT_ETH_HEADER pEthHeader = NULL;
53: ULONG ulOffset = 0;
54: ULONG ulBufferLength = 0;
55: PNET_BUFFER pCurrentNetBuffer = NULL;
56: PNET_BUFFER pPreviousNetBuffer = NULL;
57: PNET_BUFFER pNewNetBuffer = NULL;
58: ULONG ulTotalLength = 0;
59:
60: DEBUGP(DL_TRACE, ("===>SendNetBufferList: NBL = %p.\n", NetBufferLists));
61:
62: // do
63: // {
64: //
65: // DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);
66: //#if DBG
67: // //
68: // // we should never get packets to send if we are not in running state
69: // //
70: //
71: // FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
72: // //
73: // // If the filter is not in running state, fail the send
74: // //
75: // if (pFilter->State != FilterRunning)
76: // {
77: // FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
78: //
79: // CurrNbl = NetBufferLists;
80: // while (CurrNbl)
81: // {
82: // NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_PAUSED;
83: // CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
84: // }
85: // NdisFSendNetBufferListsComplete(pFilter->FilterHandle,
86: // NetBufferLists,
87: // DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
88: // break;
89: //
90: // }
91: // FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
92: //#endif
93: // if (pFilter->TrackSends)
94: // {
95: // FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
96: // CurrNbl = NetBufferLists;
97: // while (CurrNbl)
98: // {
99: // pFilter->OutstandingSends++;
100: // FILTER_LOG_SEND_REF(1, pFilter, CurrNbl, pFilter->OutstandingSends);
101: //
102: // CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
103: // }
104: // FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
105: // }
106: // //
107: // // If necessary, queue the NetBufferList in a local structure for later processing
108: // //
109: // NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);
110: //
111: //
112: // }
113: // while (bFalse);
114:
115: KdBreakPoint();
116:
117:
118: pNetBufList = NetBufferLists;
119:
120: while (pNetBufList != NULL)
121: {
122: pNextNetBufList = NET_BUFFER_LIST_NEXT_NBL(pNetBufList);
123:
124: for (pCurrentNetBuffer = NET_BUFFER_LIST_FIRST_NB(pNetBufList);
125: pCurrentNetBuffer != NULL;
126: pCurrentNetBuffer = NET_BUFFER_NEXT_NB(pCurrentNetBuffer))
127: {
128: pMdl = NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer);
129: ulTotalLength = NET_BUFFER_DATA_LENGTH(pCurrentNetBuffer);
130: ulOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer);
131:
132: do
133: {
134: ASSERT(pMdl != NULL);
135: if (pMdl)
136: {
137: NdisQueryMdl(
138: pMdl,
139: &pEthHeader,
140: &ulBufferLength,
141: NormalPagePriority);
142: }
143: if (NULL == pEthHeader)
144: {
145: //
146: // The system is low on resources. Set up to handle failure
147: // below.
148: //
149: ulBufferLength = 0;
150: break;
151: }
152:
153: if (0 == ulBufferLength)
154: {
155: break;
156: }
157:
158: ASSERT(ulBufferLength > ulOffset);
159:
160: ulBufferLength -= ulOffset;
161: pEthHeader = (PNDISPROT_ETH_HEADER)((PUCHAR)pEthHeader + ulOffset);
162:
163: if (ulBufferLength < sizeof(NDISPROT_ETH_HEADER))
164: {
165: DEBUGP(DL_WARN,
166: ("ReceiveNetBufferList: runt nbl %p, first buffer length %d\n",
167: pNetBufList, ulBufferLength));
168:
169: break;
170: }
171:
172: //
173: // Check the EtherType. If the Ether type indicates presence of
174: // a tag, then the "real" Ether type is 4 bytes further down.
175: //
176: if (pEthHeader->EthType == NPROT_8021P_TAG_TYPE)
177: {
178: USHORT UNALIGNED *pEthType;
179:
180: if (ulBufferLength < (sizeof(NDISPROT_ETH_HEADER) + 4))
181: {
182: break;
183: }
184:
185: pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4);
186:
187: if (*pEthType != NPROT_ETH_TYPE)
188: {
189: break;
190: }
191: }
192: else if (pEthHeader->EthType != NPROT_ETH_TYPE)
193: {
194: break;
195: }
196:
197: //
198: // to do
199: //
200:
201: //PrintDataBuffer((PUCHAR)pEthHeader, ulBufferLength);
202: DbgPrint("Packet Length 0x%d, pMdl->ByteCount 0x%x, pMdl->Next 0x%x\n", ulBufferLength, pMdl->ByteCount, pMdl->Next);
203:
204: Status = CopyNetBuffer(pFilter,pCurrentNetBuffer, &pNewNetBuffer);
205: if (NDIS_STATUS_SUCCESS != Status)
206: {
207: break;
208: }
209:
210: if (pCurrentNetBuffer == NET_BUFFER_LIST_FIRST_NB(pNetBufList))
211: {
212: NET_BUFFER_LIST_FIRST_NB(pNetBufList) = pNewNetBuffer;
213: }
214: else
215: {
216: pPreviousNetBuffer->Next = pNewNetBuffer;
217: }
218:
219: pNewNetBuffer->Next = pCurrentNetBuffer->Next;
220: NET_BUFFER_LIST_MINIPORT_RESERVED(pNewNetBuffer)[0] = pCurrentNetBuffer;
221:
222:
223: pCurrentNetBuffer = pNewNetBuffer;
224:
225: } while (FALSE);
226:
227: pPreviousNetBuffer = pCurrentNetBuffer;
228: }
229:
230:
231: pNetBufList = pNextNetBufList;
232: }
233:
234:
235:
236: NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);
237:
238: DEBUGP(DL_TRACE, ("<===SendNetBufferList. \n"));
239: }
[MSFT.NTamd64]
%NdisLwf_Desc%=Install, MS_NdisLwf
;————————————————————————-
; Installation Section
;————————————————————————-
[Install]
AddReg=Inst_Ndi
Characteristics=0×40000
NetCfgInstanceId="{5cbf81bd-5055-47cd-9055-a76b2b4e3697}"
Copyfiles = ndislwf.copyfiles.sys
[SourceDisksNames]
1=%NdisLwf_Desc%,"",,
[SourceDisksFiles]
ndislwf.sys=1
[DestinationDirs]
DefaultDestDir=12
ndislwf.copyfiles.sys=12
[ndislwf.copyfiles.sys]
ndislwf.sys,,,2
;————————————————————————-
; Ndi installation support
;————————————————————————-
[Inst_Ndi]
HKR, Ndi,Service,,"NdisLwf"
HKR, Ndi,CoServices,0×00010000,"NdisLwf"
HKR, Ndi,HelpText,,%NdisLwf_HelpText%
HKR, Ndi,FilterClass,, Custom
HKR, Ndi,FilterType,0×00010001,0×00000001 ; 0×00000002 for a modifying filter
HKR, Ndi\Interfaces,UpperRange,,"noupper"
HKR, Ndi\Interfaces,LowerRange,,"noupper"
HKR, Ndi\Interfaces, FilterMediaTypes,,"wlan" ; 只收raw wifi,也可以加上"ethernet"
HKR, Ndi,FilterRunType, 0×00010001, 2 ;this filter must run before any protocol can bind to the below miniport
;————————————————————————-
; Service installation support
;————————————————————————-
[Install.Services]
AddService=NdisLwf,,NdisLwf_Service_Inst
[NdisLwf_Service_Inst]
DisplayName = %NdisLwf_Desc%
ServiceType = 1 ;SERVICE_KERNEL_DRIVER
StartType = 1 ;SERVICE_SYSTEM_START
ErrorControl = 1 ;SERVICE_ERROR_NORMAL
ServiceBinary = %12%\ndislwf.sys
LoadOrderGroup = NDIS
Description = %NdisLwf_Desc%
AddReg = Common.Params.reg
[Install.Remove.Services]
DelService=NdisLwf,0×200
[Common.Params.reg]
HKR, FilterDriverParams\DriverParam, ParamDesc, , "Driverparam for lwf"
HKR, FilterDriverParams\DriverParam, default, , "5"
HKR, FilterDriverParams\DriverParam, type, , "int"
HKR, FilterAdapterParams\AdapterParam, ParamDesc, , "Adapterparam for lwf"
HKR, FilterAdapterParams\AdapterParam, default, , "10"
HKR, FilterAdapterParams\AdapterParam, type, , "int"
[Strings]
Msft = "Microsoft"
NdisLwf_Desc = "NDIS Sample LightWeight Filter"
NdisLwf_HelpText = "Sample to demonstrate NDIS LightWeight Filters"
The following NDIS filter driver installation issues are associated with modifying filter drivers. To create your own modifying filter driver INF file, you can also adapt the sample NDIS 6.0 filter driver.
- Set the Class INF file entry to NetService in the INF file. The following example shows a sample Class entry for the INF file.
Class = NetService
- The DDInstall section in a filter driver INF file must have a Characteristics entry. The following example shows how you should define the Characteristics entry in your filter INF file.
Characteristics=0x40000
The 0×40000 value indicates that NCF_LW_FILTER (0×40000) is set. Filter drivers must not set the NCF_FILTER (0×400) flag. The values of the NCF_ Xxx flags are defined in Netcfgx.h. For more information about NCF_ Xxx flags, see DDInstall Section in a Network INF File.
- Set the NetCfgInstanceId INF file entry in the INF file, as the following example shows.
NetCfgInstanceId="{5cbf81bd-5055-47cd-9055-a76b2b4e3697}"You can use the Uuidgen.exe tool to create the GUID for the NetCfgInstanceId entry.
-
The DDInstall section of the INF file for a filter driver must include an Addreg directive for an Ndi key. The INF file must specify the Service entry under the Ndi key. The ServiceBinary entry in the service-install section of the INF file specifies the path to the binary for the filter driver. For more information, see Adding Service-Related Values to the Ndi Key and DDInstall.Services Section in a Network INF File.
- The DDInstall section in a filter driver INF file must have FilterType and FilterRunType entries. To specify a modifying filter, define the FilterType entry in your INF file, as the following example shows.
HKR, Ndi,FilterType,0x00010001 ,0x00000002
The FilterType value 0×00000002 indicates that the filter is a modifying filter.
- Define the FilterRunType entry in your INF file, as the following example shows.
HKR, Ndi,FilterRunType,0x00010001 ,0x00000001
The 0×00000001 value in the preceding example indicates that the filter module is mandatory. To install an optional filer module, set the FilterRunType entry to 0×00000002.
- The following example shows how a modifying filter driver INF file specifies the name of the service:
HKR, Ndi,Service,,"NdisLwf"
In this example, NdisLwf is the name of the driver’s service as it is reported to NDIS. Note that the name of a filter driver’s service can be different from the name of the binary for the driver–but typically they are the same.
- The following example shows how the filter INF file references the name of the filter driver’s service when it adds that service.
[Install.Services] AddService=NdisLwf,,NdisLwf_Service_Inst;, common.EventLog [NdisLwf_Service_Inst] DisplayName = %NdisLwf_Desc% ServiceType = 1 ;SERVICE_KERNEL_DRIVER StartType = 1 ;SERVICE_SYSTEM_START ErrorControl = 1 ;SERVICE_ERROR_NORMAL ServiceBinary = %12%\ndislwf.sys LoadOrderGroup = NDIS Description = %NdisLwf_Desc% AddReg = Common.Params.reg
- A filter INF file must specify at least the primary service name of the filter for the CoServices attribute, as the following example shows.
HKR, Ndi,CoServices,0x00010000,"NdisLwf"
For more information about the CoServices attribute, see Adding Service-Related Values to the Ndi Key.
- The FilterClass value in the INF file for a filter driver determines its order in a stack of filters. Filter drivers must define the FilterClass key. The class of the driver can be one of the values in the following table.
Value
Descriptionscheduler
Packet-scheduling filter service. This class of filter driver is the highest-level driver that can exist above encryption class filters in a driver stack. A packet scheduler detects the 802.1p priority classification that is given to packets by quality of service (QoS)-signaling components and the scheduler sends those packets levels to underlying drivers according to their priority.
Encryption
Encryption class filter drivers exist between scheduler and compression class filters.
Compression
Compression class filter drivers exist between encryption and vpn class filters.
Vpn
vpn class filter drivers exist between compression and load balance filter drivers.
Loadbalance
Load-balancing filter service. This class of filter driver exists between packet-scheduling and fail-over drivers. A load balancing filter service balances its workload of packet transfers by distributing the workload over its set of underlying miniport adapters.
failover
Fail-over filter service. This class of filter driver exists between load balance and diagnostics drivers.
Diagnostic
Diagnostic filter drivers exists below failover drivers in the stack.
Custom
Filter drivers in custom class exist below diagnostic drivers.
Note More than one filter driver of a specific class can exist in a layered stack of modifying filter drivers. For example, two modifying filter drivers of FilterClass "scheduler" can exist in a stack simultaneously. The filter driver that has a later installation timestamp is installed below (that is, closer to the miniport adapter) the filter driver with the earlier timestamp. However, the order of multiple filter drivers with the same class is exactly the same over different miniport adapters on the same computer.
The following example shows a sample FilterClass .
HKR, Ndi,FilterClass,, compression
- You must define the following entries in the modifying filter driver INF file to control the driver bindings:
HKR, Ndi\Interfaces,UpperRange,,"noupper" HKR, Ndi\Interfaces,LowerRange,,"nolower" HKR, Ndi\Interfaces, FilterMediaTypes,,"ethernet"
For more information about controlling the driver bindings, see Specifying Filter Driver Binding Relationships.
- A modifying filter INF file should specify common parameter definitions for the driver and parameters that are associated with a specific adapter. The following example shows some common parameter definitions.
[Common.Params.reg] HKR, FilterDriverParams\DriverParam, ParamDesc, , "Driverparam for lwf" HKR, FilterDriverParams\DriverParam, default, , "5" HKR, FilterDriverParams\DriverParam, type, , "int" HKR, FilterAdapterParams\AdapterParam, ParamDesc, , "Adapterparam for lwf" HKR, FilterAdapterParams\AdapterParam, default, , "10" HKR, FilterAdapterParams\AdapterParam, type, , "int"
Send comments about this topic to Microsoft
Build date: 2/9/2011
© 2011 Microsoft. All rights reserved.
NdisAllocateNetBufferMdlAndData分配出来的NET_BUFFER,初始值CurrentMdl指向MdlChain。
CurrentMdlOffset和DataOffset都是Buffer的长度,所以在用之前一定要先初始化。
NDIS 6.0开始用这个结构,就相当于以前的NDIS_PACKET。NET_BUFFER_LIST里面连接的多个NET_BUFFER就是同一TCP连接或UDP里的一系列的包。而NET_BUFFER_LIST之间也就谁也不鸟谁了,可能是完全不搭界的包,向上下层提交的时候也可以以NET_BUFFER_LIST为单位分着来。
一般NDIS接收的包都是一整块内存,发的时候内存是分块的。现在没有了NDIS_BUFFER,直接用MDL了。
NET_BUFFER结构里CurrentMdl和MdlChain比较有意思。按我的理解是,比如MdlChain里可以串几个MDL,比如说3个,但我可以让CurrentMdl指向第2个,当发出去或者收进来的时候,都以第2个为开始,相当于MdlChain[0]只是挂在那,它的内容完全完全被忽略。
这张图里的是我随便断下来的一个包,NET_BUFFER->Next是空。也就是只是单独的一个数据包或者说Eth Frame。CurrentMdl和MdlChain指向的是同一个MDL。
CurrentMdlOffset表示包内容在MDL(指示的内存)里的偏移,也就是 包内容起始位置 = MDL’s MappedSystemVa + CurrentMdlOffset。
DataOffset按上面说的那种情况貌似就应该是 包内容起始位置 = MdlChain[0]’s length + CurrentMdl’s MappedSystemVa +CurrentMdlOffset。
CurrentMdl里面连着另一个MDL,这个是从发包的时候断下来的,发出去的包基本上都是分层的。
NET_BUFFER->DataLength是数据的长度,在图片里的这种情况里:
DataLength = CurrentMdl->ByteCount – CurrentMdlOffset + NextMdl’s ByteCount
如果CurrentMdl->ByteCount – CurrentMdlOffset 小于DataLength,说明数据不只在一个MDL里,后面还有。
stDataLength不知道干嘛的。
很奇怪, Win7 pdb里的NET_BUFFER结构和WDK文档里的不一样
kd> dt ndis!_NET_BUFFER
+0×000 Next : Ptr32 _NET_BUFFER
+0×004 CurrentMdl : Ptr32 _MDL
+0×008 CurrentMdlOffset : Uint4B
+0×00c DataLength : Uint4B
+0×00c stDataLength : Uint4B
+0×010 MdlChain : Ptr32 _MDL
+0×014 DataOffset : Uint4B
+0×000 Link : _SLIST_HEADER
+0×018 ChecksumBias : Uint2B
+0×01a Reserved : Uint2B
+0×01c NdisPoolHandle : Ptr32 Void
+0×020 NdisReserved : [2] Ptr32 Void
+0×028 ProtocolReserved : [6] Ptr32 Void
+0×040 MiniportReserved : [4] Ptr32 Void
+0×050 DataPhysicalAddress : _LARGE_INTEGER
+0×058 SharedMemoryInfo : Ptr32 _NET_BUFFER_SHARED_MEMORY
+0×058 ScatterGatherList : Ptr32 _SCATTER_GATHER_LIST
1>device.obj : error LNK2019: unresolved external symbol _memcmp referenced in function _filterFindFilterModule@8
1>Release\filter.sys : fatal error LNK1120: 1 unresolved externals
再次遇到,又忘了该怎么设置了,多亏小树。。。
用/Oi
/Oi(生成内部函数)
用有助于应用程序更快运行的内部函数或其他特殊形式的函数替换某些函数调用。
/Oi[-]
使用内部函数的程序比较快,因为它们没有函数调用系统开销。但是,由于创建了附加代码,它们可能比较大。
有关有内部形式的函数的更多信息,请参见 intrinsic。
/Oi 仅作为对编译器的请求,用于将某些函数调用替换为内部函数;为产生更好的性能,编译器可能会调用函数(而不会将该函数调用替换为内部函数)。
x86 特定
注意
_alloca 和 setjmp 函数始终内联生成;此行为不受 /Oi 影响。
内部浮点函数不对输入值执行任何特殊检查,因此只在有限的输入范围内有效,且与同名库例程具有不同的异常处理和边界条件。使用真正的内部形式意味着失去 IEEE 异常处理以及失去 _matherr 和 errno 功能;后者意味着失去 ANSI 一致性。然而,内部形式可以显著提高浮点密集型程序的速度,而且对于很多程序来说,一致性问题几乎没有任何价值。
可以使用 /Za、/Ze(禁用语言扩展)重写真正的内部浮点选项的生成。在这种情况下,函数生成为库例程,后者将参数直接传递到浮点芯片,而不是将参数推送到程序堆栈上。
END x86 Specific
还可以使用 intrinsic 创建内部函数,或者使用 function (C/C++) 显式强制函数调用。
在 Visual Studio 开发环境中设置此编译器选项
-
打开该项目的“属性页”对话框。有关详细信息,请参见如何:打开项目属性页。
-
单击“C/C++”文件夹。
-
单击“优化”属性页。
-
修改“启用内部函数”属性。