实验十三:串口模块② — 接收

我们在实验十二实现了串口发送,然而这章实验则要实现串口接收 ... 在此,笔者也会使用其它思路实现串口接收。

图13.1 模块之间的数据传输。

假设我们不考虑波特率,而且一帧数据之间的传输也只是发生在FPGA之间,即两只模块之间互转,并且两块模块都使用相同的时钟频率,结果如图13.1所示。只要成立上述的假设成立,串口传输不过是简单的数据传输活动而已,图中的发送模块经由TXD将一帧11位的数据发送至接收模块。

图13.2 发送与接收一帧数据。

至于两者之间的时序过程,则如图13.2所示 ... 发送方经由TXD,从T0~T10总共发送一帧为11位的数据,反之接收方则从T2~T9读取其中的8位数据而已(D为寄存器的暂存内容)。从图13.2当中,我们可以看见发送方,即TXD都是经由上升沿发送未来值,接收方D则是经由上升沿读取过去值。对此,Verilog可以这样描述,结果如代码13.1所示:

      //发送方
      reg [10:0]rTXD;
     always @(posedge CLOCK)
         case(i)
            0,1,2,3,4,5,6,7,8,9,10:      
            begin TXD <= rTXD[i]; i <= i + 1'b1; end
            ......
         endcase
 
      //接收方
      reg [7:0]D1;
     always @(posedge CLOCK)
         case(i)
           2,3,4,5,6,7,8,9:      
            begin D1[i] <= TXD; i <= i + 1'b1; end
            ......
         endcase

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

代码13.1

如代码13.1所示,发送方在步骤0~10一共发送一帧为11位的数据 ... 反之接收方,则在步骤2~9读取其中的数据[7:0]。心机重的朋友的一定会疑惑道,为什么笔者要换个角度去思考串口怎样接收呢?原因其实很简单,目的就是为了简化理解,脑补时序,实现精密控制。

对此,FPGA与其它设备互转数据,其实可以反映成两只模块正在互转数据,然而理想时序就是关键。因为Verilog无法描述理想以外的时序,对此所有时序活动都必须看成理想时序。

图13.3 FPGA接收一帧波特率为115200的数据。

当FPGA接收一帧数据为波特率115200之际,情况差不多如图13.3所示。50Mhz是FPGA的时钟源,也是一帧数据的采集时钟,RXD则是一帧数据的输入端。波特率为115200的一位数据经过50Mhz的时钟量化以后,每一位数据大约保持8.68us,即434个时钟。

串口传输没有自己的时钟信号,所以我们必须利用FPGA的时钟源“跟踪”每一位数据。对此,FPGA只能借用计数器“同步跟踪”而已,至于Verilog则可以这样描述,结果如代码13.2所示:

    0,1,2,3,4,5,6,7,8,9,10:  //同步跟踪中 ...        
    if( C1 == 434 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end
    else C1 <= C1 + 1'b1; 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

代码13.2

如代码13.2所示,所谓同步跟踪,就是利用计数器估计每一位数据 ... 期间,步骤0~10表示每一位数据,至于C1计数434个时钟则是同步跟踪中。其中 -1 考虑了步骤之间的跳转所耗掉的时钟。

图13.4 读取起始位。

我们都知道串口的一帧数据都是从拉低的起始位开始,然而为了完美尾行,亦即实现精密控时,起始位的读取往往都是关键。如图13.4所示,当我们在第一个时钟读取(采集)起始位的时候,由于Verilog的读取只能经过读取过去值而已,余下起始位还有433个时钟需要我们跟踪,为此Verilog可以这样描述,结果如代码13.3所示:

    0: 
    if( RXD == 1'b0 ) begin i <= i + 1'b1; C1 <= C1 + 4'd1; end         
         
    1: // stalk start bit
    if( C1 == BPS115K2 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end 
    else C1 <= C1 + 1'b1;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

代码13.3

如代码13.3所示,步骤0用来检测起始位,如果RXD的电平为拉低状态,C1立即递增以示同步跟踪已经用掉一个时钟,同样也可以看成i进入下一个步骤用掉一个时钟。然而步骤1是用来跟踪余下的433个时钟,但是计数器C1不是从0开始计数,而是从1开始计算,因为C1在步骤已经递增的缘故。

图13.5 读取一帧数据当中的数据位。

一帧数据的跟踪结果与读取结果如图13.5所示 ... 除了起始位,我们使用了两个步骤采集并跟踪之余,接下来便用8个步骤数据一边跟踪一边采集所有数据位,然而采集的时候则是1/4周期,即每位数据的第108个时钟。最后的校验位及结束位则是跟踪而已。对此,Verilog 可以这样表示,结果如代码13.4所示:

    0: 
    if( RXD == 1'b0 ) begin i <= i + 1'b1; C1 <= C1 + 4'd1; end 
                     
    1: // start bit
    if( C1 == 434 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end 
    else C1 <= C1 + 1'b1;
                     
    2,3,4,5,6,7,8,9: 
    begin
        if( C1 == 108 ) D1[i-2] <= RXD;
        if( C1 == 434 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end
        else C1 <= C1 + 1'b1;                           
    end
                 
    10,11: // parity bit & stop bit
    if( C1 == 434 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end
    else C1 <= C1 + 1'b1;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

代码13.4

如代码13.4所示,步骤0~1用来采集与跟踪起始位,步骤2~9则用来跟踪数据位,并且采集为1/4周期。步骤10~11则用来跟踪校验位于结束位。理解完毕以后,我们便可以开始建模了。

图13.6 实验十三的建模图。

图13.6是实验十三的建模图,rx_demo组合模块包含RX功能模块与核心操作。RX功能模块的左方链接至RXD顶层信号,它主要是负责一帧数据的接收,然后反馈给核心操作。核心操作则负责RX功能模块的使能工作,当它领取完成信号以后,变桨回收回来的数据再经由TXD顶层信号发送出去。

rx_funcmod.v

图13.7 RX功能模块的建模图。

图13.7是RX功能模块的建模图,左方链接至顶层信号RXD,右方则是问答信号还有8位的oData。

1.    module rx_funcmod
2.    (
3.         input CLOCK, RESET, 
4.         input RXD,
5.         input iCall,
6.         output oDone, 
7.         output [7:0]oData
8.    );
9.        parameter BPS115K2 = 9'd434, SAMPLE = 9'd108;
10.          

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容是相关的出入端声明,第9行则是波特率为115200的常量声明,其外还有采集的周期。

11.         reg [3:0]i;
12.         reg [8:0]C1;
13.         reg [7:0]D1;
14.         reg isDone;
15.         
16.         always @ ( posedge CLOCK or negedge RESET )
17.             if( !RESET )
18.                  begin
19.                         i <= 4'd0;
20.                         C1 <= 9'd0;
21.                         D1 <= 8'd0;
22.                         isDone <= 1'b0;
23.                    end

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容行是相关的寄存器声明,第17~22行则是这些寄存器的复位操作。

24.              else if( iCall )
25.                  case( i )
26.                         
27.                         0: 
28.                         if( RXD == 1'b0 ) begin i <= i + 1'b1; C1 <= C1 + 4'd1; end 
29.                         
30.                         1: // start bit
31.                         if( C1 == BPS115K2 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end 
32.                         else C1 <= C1 + 1'b1;
33.                         
34.                         2,3,4,5,6,7,8,9: //stalk and count 1~8 data's bit , sample data at 1/2 for bps
35.                         begin
36.                            if( C1 == SAMPLE ) D1[i-2] <= RXD;
37.                            if( C1 == BPS115K2 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end
38.                            else C1 <= C1 + 1'b1;          
39.                         end
40.                         
41.                         10,11: // parity bit & stop bit
42.                         if( C1 == BPS115K2 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end
43.                         else C1 <= C1 + 1'b1;
44.                         
45.                         12:
46.                         begin isDone <= 1'b1; i <= i + 1'b1; end
47.                         
48.                         13:
49.                         begin isDone <= 1'b0; i <= 4'd0; end
50.                    
51.                    endcase
52.                    

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容是核心操作。第24行的 if( iCall ) 表示该模块不使能便不工作。步骤0~1用来判断与跟踪起始位;步骤2~9用来跟踪并且读取当中的数据位;步骤10至11则是用来跟踪校验位与停止位而已。步骤12~13则用来反馈完成信号,以示一次性的接收工作已经完成。

53.        assign oDone = isDone;
54.        assign oData = D1;
55.        
56.    endmodule

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容是输出驱动声明。

rx_demo.v

rx_demo的连线布局请浏览回图13.6,至于核心操作的内容请浏览代码。

1.    module rx_demo
2.    (
3.         input CLOCK, RESET, 
4.         input RXD,
5.         output TXD
6.    );

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容是相关的出入端声明。

7.         wire DoneU1;
8.         wire [7:0]DataU1;
9.        
10.        rx_funcmod U1
11.         (
12.             .CLOCK( CLOCK ),
13.              .RESET( RESET ),
14.              .RXD( RXD ),    // < top
15.              .iCall( isRX ),    // < core
16.              .oDone( DoneU1 ),  // > core
17.              .oData( DataU1 )   // > core
18.         );
19.         

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容为是RX功能模块的实例化,第7~8是连线声明。

20.         parameter B115K2 = 9'd434, TXFUNC = 5'd16;
21.         
22.         reg [4:0]i,Go;
23.         reg [8:0]C1;
24.         reg [10:0]D1;
25.         reg rTXD;
26.         reg isRX;
27.         
28.         always @ ( posedge CLOCK or negedge RESET )
29.             if( !RESET )
30.                  begin 
31.                         i <= 5'd0;
32.                         C1 <= 9'd0;
33.                         D1 <= 11'd0;
34.                         rTXD <= 1'b1;
35.                         isRX<= 1'b0;
36.                    end

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容为相关的寄存器声明以及复位操作。第20行是波特率为115200常量声明之余还有伪函数的入口地址。第22~26行是相关的寄存器声明,第29~33行则是这些寄存器的复位操作。

37.              else
38.                  case( i )
39.                    
40.                         0:
41.                         if( DoneU1 ) begin isRX <= 1'b0; D1 <= { 2'b11,DataU1,1'b0 }; i <= TXFUNC; Go <= 5'd0; end
42.                         else isRX <= 1'b1; 
43.                         
44.                         /**********/
45.                         
46.                         16,17,18,19,20,21,22,23,24,25,26:
47.                         if( C1 == B115K2 -1 ) begin C1 <= 8'd0; i <= i + 1'b1; end
48.                         else begin rTXD <= D1[i - 16]; C1 <= C1 + 1'b1; end
49.                         
50.                         27:
51.                         i <= Go;
52.                        
53.                    endcase
54.                    

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容为核心操作。步骤16~27是发送一帧数据的伪函数,笔者直接将TX功能整合进来。步骤0则是用来接收完成反馈,并且准备好发送输数,然后i指向伪函数。

55.        assign TXD = rTXD;
56.
57. endmodule

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

以上内容是相关的输出驱动声明。编译完毕便下载程序,串口调试助手设置为 115200 波特率,8位数据位,奇偶校验位随便,停止位1。事后,每当串口调试助手想FPGA发送什么数据,FPGA也会回馈串口调试助手,不过仅限于一帧又有间隔的数据而已。目前是实验十三还不能支持数据流的接收,因为实验十三没有空间缓冲数据流 ... 此外,核心操作没发送一帧数据也有一定的时间耽误。

细节一:完整的个体模块

实验十三的RX功能模块已经是完整的个体模块,可以直接拿来调用。

【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十三:串口模块② — 接收的更多相关文章

  1. [黑金原创教程] FPGA那些事儿《设计篇 III》- 图像处理前夕·再续

    简介 一本为入门图像处理的入门书,另外还教你徒手搭建平台(片上系统),内容请看目录. 注意 为了达到最好的实验的结果,请准备以下硬件. AX301开发板, OV7670摄像模块, VGA接口显示器, ...

  2. [黑金原创教程] FPGA那些事儿《设计篇 II》- 图像处理前夕·续

    简介 一本为入门图像处理的入门书,另外还教你徒手搭建平台(片上系统),内容请看目录. 注意 为了达到最好的实验的结果,请准备以下硬件. AX301开发板, OV7670摄像模块, VGA接口显示器, ...

  3. [黑金原创教程] FPGA那些事儿《设计篇 I》- 图像处理前夕

    简介 一本为入门图像处理的入门书,另外还教你徒手搭建平台(片上系统),内容请看目录. 注意 为了达到最好的实验的结果,请准备以下硬件. AX301开发板, OV7670摄像模块, VGA接口显示器, ...

  4. [黑金原创教程] FPGA那些事儿《数学篇》- CORDIC 算法

    简介 一本为完善<设计篇>的书,教你CORDIC算法以及定点数等,内容请看目录. 贴士 这本教程难度略高,请先用<时序篇>垫底. 目录 Experiment 01:认识CORD ...

  5. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】原创教程连载导读【连载完成,共二十九章】

    前言: 无数昼夜的来回轮替以后,这本<驱动篇I>终于编辑完毕了,笔者真的感动到连鼻涕也流下来.所谓驱动就是认识硬件,还有前期建模.虽然<驱动篇I>的硬件都是我们熟悉的老友记,例 ...

  6. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】连载导读

    前言: 无数昼夜的来回轮替以后,这本<驱动篇I>终于编辑完毕了,笔者真的感动到连鼻涕也流下来.所谓驱动就是认识硬件,还有前期建模.虽然<驱动篇I>的硬件都是我们熟悉的老友记,例 ...

  7. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验七:PS/2模块① — 键盘

    实验七:PS/2模块① — 键盘 实验七依然也是熟烂的PS/2键盘.相较<建模篇>的PS/2键盘实验,实验七实除了实现基本的驱动以外,我们还要深入解PS/2时序,还有PS/2键盘的行为.不 ...

  8. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十:PS/2模块④ — 普通鼠标

    实验十:PS/2模块④ - 普通鼠标 学习PS/2键盘以后,接下来就要学习 PS/2 鼠标.PS/2鼠标相较PS/2键盘,驱动难度稍微高了一点点,因为FPGA(从机)不仅仅是从PS/2鼠标哪里读取数据 ...

  9. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验六:数码管模块

    实验六:数码管模块 有关数码管的驱动,想必读者已经学烂了 ... 不过,作为学习的新仪式,再烂的东西也要温故知新,不然学习就会不健全.黑金开发板上的数码管资源,由始至终都没有改变过,笔者因此由身怀念. ...

随机推荐

  1. 在Android平台下搭建PhoneGap开发环境--用HTML5开发游戏

    一.在Android平台下搭建PhoneGap开发环境具体怎么搭建我这里就不详细说了,如有需要我后面再讲 . PhoneGap 官方地址有详细说明:http://www.phonegap.com. 在 ...

  2. [AngularJS] tips技巧收集

     单个参数调用angular.module(),用来取得该模块而不是定义新的 这样就可以在不同的地方定义app的controller而不用通过全局变量 angular.module('myapp') ...

  3. cp -rf 提示覆盖解决办法

    cp覆盖时,无论加什么参数-f之类的还是提示是否覆盖,当文件比较少的时候还可以按Y确认,当很多文件的时候就不好说了 方法一:vi ~/.bashrc # .bashrc # User specific ...

  4. 如何使用 MasterPage

    MasterPageFile母版页 刚开始学,什么都不懂,看到了这段代码,才促使自己去研究MasterPageFile到底是什么含义.<%@ Page Language="C#&quo ...

  5. [转]IOS 崩溃日志分析

    以下是一个crash log示例: // 1: Process Information Incident Identifier: 30E46451-53FD--896A-457FC11AD05F Cr ...

  6. 5 -- Hibernate的基本用法 --3 Hibernate的体系结构

    ⊙ SessionFactory : 这是Hibernate的关键对象,它是单个数据库映射关系经过编译后的内存镜像,也是线程安全的.它是生成Session的工厂,本身需要依赖于ConnectionPr ...

  7. c 网络字节序和本机字节序转换

    将多字节整数类型的数据,从主机的字节顺序转化为网络字节顺序 #include <netinet/in.h> uint32_t htonl(uint32_t hostlong);uint16 ...

  8. 基于端口的弱口令检测工具--iscan

    亲手打造了一款弱口令检测工具,用Python编写,主要可以用于内网渗透.弱口令检测等方面,目前集成了常见端口服务,包含 系统弱口令:ftp.ssh.telnet.ipc$ 数据库弱口令:mssql.m ...

  9. Explaining Delegates in C# - Part 7 (Asynchronous Callback - Way 4)

    This is the final part of the series that started with... Callback and Multicast delegatesOne more E ...

  10. 关于 g++ 编译器

    g++由自由软件基金发行,g++是基于类unix的c++编译器,通常在命令行运行.它一般附带于类Unix系统中,因此如果你正在运行Unix或Linux系统,它很可能已经存在于你的系统中.你可以对一个源 ...