买了一个开发板学习FPGA,找到的各种东西就记录在这个博客里了,同时也方便把自己不会的问题找到的结果记录一下,都是自己手打,所以可能说的话不那么严谨,不那么精准,看到的人要带着自己的思考去看,记住尽信书不如无书,哈哈哈。。。。。。

 一、UART是什么?

UART是一种通用串行数据总线,也就是用于数据传输。是用于主机与辅助设备进行通信。这里的主机理解为计算机,计算机内部采用并行数据,辅助设备采用串行数据。中间需要设备进行数据转换,这也决定了UART工作原理是将传输数据的每个字符一位接一位地传输。UART采用异步传输模式,异步传输将比特分成小组进行传送,小组可以是8位的1个字符或更长。发送方可以在任何时刻发送这些比特组,而接收方从不知道它们会在什么时候到达。例如计算机键盘与主机的通信。UART用于远距离传输较为适合。可以数据同时发送和接收。

1,异步传输是面向字符的传输,而同步传输是面向比特的传输。

                                                2,异步传输的单位是字符而同步传输的单位是帧。
                                                3,异步传输通过字符起始和停止码抓住再同步的机会,而同步传输则是在数据中抽取同步信息。
                                                4,异步传输对时序的要求较低,同步传输往往通过特定的时钟线路协调时序。
                                                5,异步传输相对于同步传输效率较低。
我的理解是对时序要求是采用UART的原因,数据到达需要给出到达信号也解释了UART采用8位1字符的串行数据输出模式,也解释了协议中起始位与停止位的重要性。
uart指通用异步收发传输器,本质上是硬件,用来异步传输数据。RS232是一种物理层协议,规定了特定的接口标准。https://www.zhihu.com/question/22632011 
进行数据传输时,需要考虑时钟同步问题,传输速率有一个很重要的概念。波特率是衡量资料传送速率的指标。表示每秒钟传送的符号数(symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如资料传送速率为120字符/秒,传输使用256阶符号,每个符号代表8bit,则波特率就是120baud,比特率是120*8=960bit/s。位 bit (比特)(Binary Digits):存放一位二进制数,即 0 或 1,最小的存储单位。字节Byte:8个二进制位为一个字节(B),最常用的单位。
常用波特率9600,19200,38400,115200等。
其中各位的意义如下: 
起始位:先发出一个逻辑”0”信号,表示传输字符的开始。 
数据位:可以是5~8位逻辑”0”或”1”。如ASCII码(7位),扩展BCD码(8位)。 
校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验)。 
停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 
空闲位:处于逻辑“1”状态,表示当前线路上没有资料传送。

     二、UART串口通信一般包括部分
    任何程序都包括一个主控制程序,因为是双向通信,还需要串口发送程序,串口接收程序,时钟控制程序。举例来分别解释四个程序的代码。
      这里采用50MHz的系统时钟,产生UART时钟信号产生和发送的波特率为9600bps。为了保证采样的时候不会发生误码或者滑码,我们对于一位数据不只采用一个时钟周期进行数据采集,而采用16个时钟周期。那么就需要对时钟进行分频处理。50,000,000/(16*9600),分频系数取整为326 。偶数分频比较简单,此处采用了326,至于奇数分频以及如何做出占空比为50%以后整理。
 1 `timescale 1ns / 1ps
 2 //
 3 // Module Name:    clkdiv
 4 // 产生一个波特率9600的16倍频的时钟,9600*16= 153600
 5 // 相当于50MHz的326分频,50000000/153600=326
 6 //
 7 module clkdiv(clk50, clkout);
 8 input clk50;              //系统时钟
 9 output clkout;          //采样时钟输出
10 reg clkout;
11 reg [15:0] cnt;
12
13 //分频进程,对50Mhz的时钟326分频
14 always @(posedge clk50)
15 begin
16   if(cnt == 16'd162)
17   begin
18     clkout <= 1'b1;
19     cnt <= cnt + 16'd1;
20   end
21   else if(cnt == 16'd325)
22   begin
23     clkout <= 1'b0;
24     cnt <= 16'd0;
25   end
26   else
27   begin
28     cnt <= cnt + 16'd1;
29   end
30 end
31 endmodule

分频比较简单,我写的另一个,

 1  `timescale 1ns / 1ps
 2
 3  module clkdiv(clk50, clkout);
 4  input clk50;              //系统时钟
 5  output clkout;          //采样时钟输出
 6  reg clkout;
 7  reg [15:0] cnt;
 8
 9 always @(posedge clk50)
10     begin
11       if (cnt < 16'd162)
12       cnt <= cnt + 16'b1;
13      else  if  (cnt == 16'd162)
14       begin
15           clkout <= ~clkout;
16           cnt <= 16'b0;
17       end
18      end


三、串口发送程序

UART采用异步传输,就涉及起始位与停止位,下面是代码例子,我的总结用红笔标出。

  1 `timescale 1ns / 1ps
  2 //
  3 // Module Name:    uarttx
  4 // 说明:16个clock发送一个bit,
  5 //
  6 module uarttx(clk, datain, wrsig, idle, tx);
  7 input clk;                //UART时钟
  8 input [7:0] datain;       //需要发送的数据
  9 input wrsig;              //发送命令,上升沿有效
 10 output idle;              //线路状态指示,高为线路忙,低为线路空闲
 11 output tx;                //发送数据信号
 12 reg idle, tx;
 13 reg send;
 14 reg wrsigbuf, wrsigrise;
 15 reg presult;
 16 reg[7:0] cnt;             //计数器
 17 parameter paritymode = 1'b0;
 18
 19 //检测发送命令是否有效,判断wrsig的上升沿            //先检测发送命令是否有效,然后判断线路状态
 20 always @(posedge clk)
 21 begin
 22    wrsigbuf <= wrsig;
 23    wrsigrise <= (~wrsigbuf) & wrsig;         //边沿检测,检测发送命令
 24 end
 25
 26 always @(posedge clk)
 27 begin
 28   if (wrsigrise &&  (~idle))  //当发送命令有效且线路为空闲时,启动新的数据发送进程
 29   begin
 30      send <= 1'b1;
 31   end
 32   else if(cnt == 8'd168)      //一帧资料发送结束
 33   begin
 34      send <= 1'b0;
 35   end
 36 end
 37
 38 /
 39 //使用168个时钟发送一个数据(起始位、8位数据、奇偶校验位、停止位),每位占用16个时钟//    //停止位为8个时钟周期
 40
 41 always @(posedge clk)
 42 begin
 43   if(send == 1'b1)  begin
 44     case(cnt)                 //tx变低电平产生起始位,0~15个时钟为发送起始位
 45     8'd0: begin
 46          tx <= 1'b0;
 47          idle <= 1'b1;
 48          cnt <= cnt + 8'd1;
 49     end
 50     8'd16: begin
 51          tx <= datain[0];    //发送数据位的低位bit0,占用第16~31个时钟
 52          presult <= datain[0]^paritymode;     //奇偶校验位的获取 53          idle <= 1'b1;
 54          cnt <= cnt + 8'd1;
 55     end
 56     8'd32: begin
 57          tx <= datain[1];    //发送数据位的第2位bit1,占用第47~32个时钟
 58          presult <= datain[1]^presult;
 59          idle <= 1'b1;
 60          cnt <= cnt + 8'd1;
 61     end
 62     8'd48: begin
 63          tx <= datain[2];    //发送数据位的第3位bit2,占用第63~48个时钟
 64          presult <= datain[2]^presult;
 65          idle <= 1'b1;
 66          cnt <= cnt + 8'd1;
 67     end
 68     8'd64: begin
 69          tx <= datain[3];    //发送数据位的第4位bit3,占用第79~64个时钟
 70          presult <= datain[3]^presult;
 71          idle <= 1'b1;
 72          cnt <= cnt + 8'd1;
 73     end
 74     8'd80: begin
 75          tx <= datain[4];   //发送数据位的第5位bit4,占用第95~80个时钟
 76          presult <= datain[4]^presult;
 77          idle <= 1'b1;
 78          cnt <= cnt + 8'd1;
 79     end
 80     8'd96: begin
 81          tx <= datain[5];    //发送数据位的第6位bit5,占用第111~96个时钟
 82          presult <= datain[5]^presult;
 83          idle <= 1'b1;
 84          cnt <= cnt + 8'd1;
 85     end
 86     8'd112: begin
 87          tx <= datain[6];    //发送数据位的第7位bit6,占用第127~112个时钟
 88          presult <= datain[6]^presult;
 89          idle <= 1'b1;
 90          cnt <= cnt + 8'd1;
 91     end
 92     8'd128: begin
 93          tx <= datain[7];    //发送数据位的第8位bit7,占用第143~128个时钟
 94          presult <= datain[7]^presult;
 95          idle <= 1'b1;
 96          cnt <= cnt + 8'd1;
 97     end
 98     8'd144: begin
 99          tx <= presult;      //发送奇偶校验位,占用第159~144个时钟      //将计算结果作为奇偶校验码输出
100          presult <= datain[0]^paritymode;     //无意思,此行计算结果无用,多余101          idle <= 1'b1;
102          cnt <= cnt + 8'd1;
103     end
104     8'd160: begin
105          tx <= 1'b1;         //发送停止位,占用第160~167个时钟
106          idle <= 1'b1;
107          cnt <= cnt + 8'd1;
108     end
109     8'd168: begin
110          tx <= 1'b1;
111          idle <= 1'b0;       //一帧资料发送结束
112          cnt <= cnt + 8'd1;
113     end
114     default: begin
115           cnt <= cnt + 8'd1;
116     end
117    endcase
118   end
119   else  begin
120     tx <= 1'b1;
121     cnt <= 8'd0;
122     idle <= 1'b0;
123   end
124 end
125 endmodule


四、串口接收程序

成为UART接收信号,将一位一位的串口数据转化为并行数据。

  1 `timescale 1ns / 1ps
  2 //
  3 // Module name    uartrx.v
  4 // 说明:          16个clock接收一个bit,16个时钟采样,取中间的采样值
  5 //
  6 module uartrx(clk, rx, dataout, rdsig, dataerror, frameerror);
  7 input clk;             //采样时钟
  8 input rx;              //UART数据输入
  9 output dataout;        //接收数据输出
 10 output rdsig;          //接收数据有效,高说明接收到一个字节 ,来区分数据处于接收状态或者接收控制信号
 11 output dataerror;      //数据出错指示
 12 output frameerror;     //帧出错指示
 13
 14 reg[7:0] dataout;
 15 reg rdsig, dataerror;
 16 reg frameerror;
 17 reg [7:0] cnt;
 18 reg rxbuf, rxfall, receive;
 19 parameter paritymode = 1'b0;
 20 reg presult, idle;
 21
 22 always @(posedge clk)   //检测线路rx的下降沿, 线路空闲的时候rx为高电平
 23 begin
 24   rxbuf <= rx;
 25   rxfall <= rxbuf & (~rx);      //下降沿检测,检测是否接收到接收信号 26 end
 27
 28 always @(posedge clk)
 29 begin
 30   if (rxfall && (~idle))  //检测到线路的下降沿并且原先线路为空闲,启动接收数据进程
 31   begin
 32     receive <= 1'b1;      //开始接收数据
 33   end
 34   else if(cnt == 8'd168)  //接收数据完成
 35   begin
 36    receive <= 1'b0;
 37   end
 38 end
 39
 40 /
 41 //使用176个时钟接收一个数据(起始位、8位数据、奇偶校验位、停止位),每位占用16个时钟//
 42
 43 always @(posedge clk)
 44 begin
 45   if(receive == 1'b1)
 46   begin
 47    case (cnt)
 48    8'd0:                   //0~15个时钟为接收第一个比特,起始位
 49      begin
 50       idle <= 1'b1;
 51       cnt <= cnt + 8'd1;
 52       rdsig <= 1'b0;
 53      end
 54    8'd24:                  //16~31个时钟为第1个bit数据,取中间第24个时钟的采样值          //在发送程序中,第0位数据在16个时钟周期后开始传输,接收过程中,
 55     begin                           //从第24个时钟周期开始接收第0位数据,保证信号被采集。
 56       idle <= 1'b1;
 57       dataout[0] <= rx;
 58       presult <= paritymode^rx;
 59       cnt <= cnt + 8'd1;
 60       rdsig <= 1'b0;
 61      end
 62    8'd40:                 //47~32个时钟为第2个bit数据,取中间第40个时钟的采样值
 63     begin
 64       idle <= 1'b1;
 65       dataout[1] <= rx;
 66       presult <= presult^rx;
 67       cnt <= cnt + 8'd1;
 68       rdsig <= 1'b0;
 69      end
 70    8'd56:                 //63~48个时钟为第3个bit数据,取中间第56个时钟的采样值
 71     begin
 72       idle <= 1'b1;
 73       dataout[2] <= rx;
 74       presult <= presult^rx;
 75       cnt <= cnt + 8'd1;
 76       rdsig <= 1'b0;
 77      end
 78    8'd72:                //79~64个时钟为第4个bit数据,取中间第72个时钟的采样值
 79     begin
 80       idle <= 1'b1;
 81       dataout[3] <= rx;
 82       presult <= presult^rx;
 83       cnt <= cnt + 8'd1;
 84       rdsig <= 1'b0;
 85      end
 86    8'd88:               //95~80个时钟为第5个bit数据,取中间第88个时钟的采样值
 87     begin
 88       idle <= 1'b1;
 89       dataout[4] <= rx;
 90       presult <= presult^rx;
 91       cnt <= cnt + 8'd1;
 92       rdsig <= 1'b0;
 93      end
 94    8'd104:             //111~96个时钟为第6个bit数据,取中间第104个时钟的采样值
 95     begin
 96       idle <= 1'b1;
 97       dataout[5] <= rx;
 98       presult <= presult^rx;
 99       cnt <= cnt + 8'd1;
100       rdsig <= 1'b0;
101      end
102    8'd120:             //127~112个时钟为第7个bit数据,取中间第120个时钟的采样值
103     begin
104       idle <= 1'b1;
105       dataout[6] <= rx;
106       presult <= presult^rx;
107       cnt <= cnt + 8'd1;
108       rdsig <= 1'b0;
109      end
110    8'd136:            //143~128个时钟为第8个bit数据,取中间第136个时钟的采样值
111     begin
112       idle <= 1'b1;
113       dataout[7] <= rx;
114       presult <= presult^rx;
115       cnt <= cnt + 8'd1;
116       rdsig <= 1'b1;      //接收数据有效
117      end
118    8'd152:            //159~144个时钟为接收奇偶校验位,取中间第152个时钟的采样值
119     begin
120       idle <= 1'b1;
121       if(presult == rx)
122         dataerror <= 1'b0;
123       else
124         dataerror <= 1'b1;       //如果奇偶校验位不对,表示数据出错
125       cnt <= cnt + 8'd1;
126       rdsig <= 1'b1;
127       end
128    8'd168:            //160~175个时钟为接收停止位,取中间第168个时钟的采样值
129      begin
130      idle <= 1'b1;
131      if(1'b1 == rx)
132        frameerror <= 1'b0;
133      else
134        frameerror <= 1'b1;      //如果没有接收到停止位,表示帧出错
135      cnt <= cnt + 8'd1;
136      rdsig <= 1'b1;
137      end
138    default:
139      begin
140       cnt <= cnt + 8'd1;
141      end
142    endcase
143   end
144   else
145   begin
146     cnt <= 8'd0;
147     idle <= 1'b0;
148     rdsig <= 1'b0;
149   end
150  end
151 endmodule


五、控制程序

这里主要学习程序的调用,如何用总的控制程序完成UART数据传输。

 1 `timescale 1ns / 1ps
 2 //
 3 // Module Name:    uart_test
 4 //
 5 //
 6 module uart_test(clk50, rx, tx, reset);
 7 input clk50;
 8 input reset;
 9 input rx;
10 output tx;
11
12 wire clk;       //clock for 9600 uart port
13 wire [7:0] txdata,rxdata;     //串口发送数据和串口接收数据
14
15
16
17 //产生时钟的频率为16*9600
18 clkdiv u0 (
19         .clk50                   (clk50),               //50Mhz的晶振输入
20         .clkout                  (clk)                  //16倍波特率的时钟
21  );
22
23 //串口接收程序
24 uartrx u1 (
25         .clk                     (clk),                 //16倍波特率的时钟
26       .rx                       (rx),                     //串口接收
27         .dataout                 (rxdata),              //uart 接收到的数据,一个字节
28       .rdsig                   (rdsig),               //uart 接收到数据有效
29         .dataerror               (),
30         .frameerror              ()
31 );
32
33 //串口发送程序
34 uarttx u2 (
35         .clk                     (clk),                  //16倍波特率的时钟
36        .tx                      (tx),                      //串口发送
37         .datain                  (txdata),               //uart 发送的数据
38       .wrsig                   (wrsig),                //uart 发送的数据有效
39       .idle                    ()
40
41  );

54 endmodule

就像c语言里调用子函数一样,每个 模块是并行运行的, 各个模块连接完成整个系统需要一个顶层文件(top-module) 。 顶层文件 通过调用、连接低层模块的实例来实现复杂的功能。

学习UART通信,最主要还是理解异步和串口这两个东西,方便远距离传输,串口一位一位传输,牺牲了时间降低时序要求。

转载于:https://www.cnblogs.com/uiojhi/p/7531478.html

串口UART学习笔记(一)相关推荐

  1. 合泰HT32 淘晶驰TJC--T0串口屏学习笔记

    串口屏开发环境搭建 串口屏的优点就不用多说了,用过的老师傅都说好! 开发专用上位机软件下载:传送门主要用来设计屏幕界面的,简单方便. 1.软件安装好后点击新建工程 2.选择你需要存放的目录,输入文件名 ...

  2. 合泰HT32--淘晶驰TJC--T0串口屏学习笔记(二)

    前言 经过上一次的串口屏学习,实现了单个页面的控件操作显示,但依旧还存在着许多需要解决的问题和优化的地方. 这次呢,主要实现串口屏多页面显示,及对应UI组件的控制. 上一篇串口屏链接:合泰HT32 & ...

  3. C#串口通信学习笔记

    因为参加一个小项目,需要对继电器进行串口控制,所以这两天学习了基本的串口编程.同事那边有JAVA的串口通信包,不过是从网上下载的,比较零乱,难以准确掌握串口通信的流程和内含.因此,个人通过学习网上大牛 ...

  4. STM32F429HAL库UART学习笔记

    UART串口通讯作为最基本通讯协议我就不多赘述.我主要用HAL库实现串口通讯,看一下配置Uart的结构一变量 这里使用了结构体嵌套 typedef struct {   USART_TypeDef   ...

  5. CC2540的HAL层UART学习笔记

    本文以TI的BLE1.3.2示例工程SimpleBLEPeripheral作关于UART的备忘笔记. 首先看hal_board_cfg.h,其中有关于底层驱动的默认配置: /* Driver Conf ...

  6. stm8s串口奇偶校验学习笔记

    特别注意:stm8的数据长度定义. 以前用过stm32的串口,不过用的时候一般都是调用库函数,设置波特率,8位数据位,无校验,1位停止位.传输过程中也没有遇到过太多的问题,最近用stm8s,需要用到奇 ...

  7. STM32F767串口通信学习笔记

    STM32F767的串口使用,需要先开启串口时钟,再设置对应的IO模式,然后配置一下波特率,数据位长度,奇偶校验位信息就可以使用了. 基础知识  STM32F767IGT6 最多可提供 8 路串口,支 ...

  8. 合泰HT32F52352串口通信学习笔记

    HT32F52352芯片资料 作为一个开发者,学会找 / 看芯片资料很重要!找资料最好的方法就是直接在官网找. 比如想找ht32f52352芯片的资料可以直接在合泰的官网下载.https://www. ...

  9. linux下串口通信详解,Linux操作系统下的串口通信学习笔记

    http://www.diybl.com/ 2008-7-5 网络 点击: [ 评论 ] - - 文章搜索:     [点击打包该文章] [本站开通在线QQ讨论群] CBAUDEX (不属于POSIX ...

  10. JAVA串口开发学习笔记1

    1.下载java Communications api开发包.  2.将win32com.dll拷贝入C:\j2sdk1.4.2_04\bin 3.将comm.jar拷贝入C:\j2sdk1.4.2_ ...

最新文章

  1. 两虎相争将带来优质的互联网搜索服务 --- 我看Google归来!
  2. bootstrapdatetimepicker 隐藏触发 bootstrap modal隐藏事件
  3. java开发的增查改删_在Java中实现增、删、改、查功能?
  4. WebLogic 12c 修改节点 Managed Server 和 AdminServer 内存方法
  5. 代码规范(一)——java篇
  6. 产业区块链:新基建中的底层技术基座,各行业资深人士应积极参与建设
  7. 全球最贵红绿灯之谜得解,原来是百度Apollo的B面
  8. 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数(day4)
  9. Hive DDL DML
  10. paip.提升中文分词准确度---新词识别
  11. Turbo C 2.0
  12. 手把手教你DosBox的配置(附下载资源)
  13. cad计算机试题及答案,CAD考试试题库及参考答案整理版.doc
  14. Little VGL + code::blocks + 模拟器
  15. Javase杂谈(四)
  16. 帝国时代2战役php文件,帝国时代各种类型文件使用说明
  17. Android Drawable图标生成工具
  18. android 语音适配,Android多语言适配繁体中文
  19. 嵌入式——独立按键控制LED显示二进制
  20. 现代A200(MoboDA3360)玩家宝典

热门文章

  1. 团队文化之舒适区和挑战区
  2. CentOS6.6 32位 Minimal版本纯编译安装Nginx Mysql PHP Memcached
  3. js td innerHTML
  4. RHEL5中配置vsftpd搭建FTP服务器
  5. 支持WI-FI的blackberry
  6. 上周Asp.net源码(11.5-11.10)免费下载列表
  7. 【c++leetcode】判断一个数是否是2的幂、3的幂、4的幂
  8. javascript 忍者秘籍读书笔记(二)
  9. hightcharts 如何修改legend图例的样式
  10. GIS应用开发AO(1)_普通几何图形绘制