16.1 介绍

  UART(Universal Asynchronous Receiver Transmitter),通用异步收发器,用来传输穿行数据时

  UART 之间以全双工方式传输数据,连线方法只有 3 根电线:TXD 用于发送数据,RXD 用于接收数据,GND用于给双方提供参考地。

  

  串口数据线以 “位”为最小单位传输数据。帧(frame)由具有完整意义的、不可分割的若干位组成,它包含开始位、数据位、校验位和停止位。

  UART 使用标准的 TTL/CMOS 逻辑电平(0~5V、0~3.3V、0~2.5V 或 0~1.8V)来表示数据,高电平表示1,低电平表示0。为了增强数据的抗干扰能力、提高传输长度,通常将 TLL/CMOS 逻辑电平转换位 RS-232 逻辑电平,3~12V 表示0,-3~-12V 表示1。

  数据的传输流程如下:

  1. 平时数据处于 空闲 状态
  2. 当要发送数据时,UART 改变 TXD 数据线的状态(变为 0 状态)并维持 1 位的时间,这样接收方检测到开始位后,再等待 1.5 位的时间就开始一位一位地检测数据线的状态得到所传输的数据
  3. UART 一帧中可以由5、6、7或8位的数据,发送方一位一位的改变数据线的状态将它们发送出去,首先发送最低位
  4. 如果使用校验功能,UART 在发送完数据位后,还要发送一个校验位。有两种校验方法:奇校验、偶校验——数据位连同校验位中,“1”的数目等于奇数或偶数
  5. 最后,发送停止位,数据线恢复到“空闲”状态(1状态)。停止位的长度有3种:1位、1.5位、2位  

16.2 S3C2440 UART 特性

  S3C2440 UART 中有3个独立的通道,每个通道都可以工作于中断模式或DMA模式,即UART可以发出中断或DMA请求以便在UART、CPU 间传输数据。UART 由波特率发生器、发送器、接收器和控制逻辑组成

  使用系统时钟时,UART的波特率可以达到 115.2Kbit/s,若使用 UEXTCLK 引脚提供的外部时钟,则可以达到更高的波特率。波特率可以通过编程进行控制。

  S3C2440 UART 的 FIFO 深度位64.。发送数据时,CPU 先将数据写入发送 FIFO 中,然后 UART 会自动将 FIFO 中的数据复制到“发送移位器”(Transmit Shifter)中,发送移位器将数据一位一位的发送到 TXDn 数据线上(根据设定的格式,插入开始位、校验位和停止位)。接收数据时,“接收移位器”(Receive Shifter)将RXDn 数据线上的数据一位一位接收进来,然后复制到接收 FIFO 中,CPU 即可以从中读取数据。

  S3C2440 UART 的每个通道支持的停止位有 1 位、2位,数据位有5、6、7、8位,支持校验功能,另外还有红外发送/接收功能。

  UART 结构图如下:

  

  其他说明见芯片手册第11章节

16.3 程序

  uart.lds

  1. SECTIONS {
  2. . = 0x30000000;
  3. .text : { *(.text) }
  4. .rodata ALIGN() : {*(.rodata)}
  5. .data ALIGN() : { *(.data) }
  6. .bss ALIGN() : { *(.bss) *(COMMON) }
  7. }

  s3c24xx.h

  1. /* WOTCH DOG register */
  2. #define WTCON (*(volatile unsigned long *)0x53000000)
  3.  
  4. /* SDRAM regisers */
  5. #define MEM_CTL_BASE 0x48000000
  6. #define SDRAM_BASE 0x30000000
  7.  
  8. /* NAND Flash registers */
  9. #define NFCONF (*(volatile unsigned int *)0x4e000000)
  10. #define NFCMD (*(volatile unsigned char *)0x4e000004)
  11. #define NFADDR (*(volatile unsigned char *)0x4e000008)
  12. #define NFDATA (*(volatile unsigned char *)0x4e00000c)
  13. #define NFSTAT (*(volatile unsigned char *)0x4e000010)
  14.  
  15. /*GPIO registers*/
  16. #define GPBCON (*(volatile unsigned long *)0x56000010)
  17. #define GPBDAT (*(volatile unsigned long *)0x56000014)
  18.  
  19. #define GPFCON (*(volatile unsigned long *)0x56000050)
  20. #define GPFDAT (*(volatile unsigned long *)0x56000054)
  21. #define GPFUP (*(volatile unsigned long *)0x56000058)
  22.  
  23. #define GPGCON (*(volatile unsigned long *)0x56000060)
  24. #define GPGDAT (*(volatile unsigned long *)0x56000064)
  25. #define GPGUP (*(volatile unsigned long *)0x56000068)
  26.  
  27. #define GPHCON (*(volatile unsigned long *)0x56000070)
  28. #define GPHDAT (*(volatile unsigned long *)0x56000074)
  29. #define GPHUP (*(volatile unsigned long *)0x56000078)
  30.  
  31. /*UART registers*/
  32. #define ULCON0 (*(volatile unsigned long *)0x50000000)
  33. #define UCON0 (*(volatile unsigned long *)0x50000004)
  34. #define UFCON0 (*(volatile unsigned long *)0x50000008)
  35. #define UMCON0 (*(volatile unsigned long *)0x5000000c)
  36. #define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
  37. #define UTXH0 (*(volatile unsigned char *)0x50000020)
  38. #define URXH0 (*(volatile unsigned char *)0x50000024)
  39. #define UBRDIV0 (*(volatile unsigned long *)0x50000028)
  40.  
  41. /*interrupt registes*/
  42. #define SRCPND (*(volatile unsigned long *)0x4A000000)
  43. #define INTMOD (*(volatile unsigned long *)0x4A000004)
  44. #define INTMSK (*(volatile unsigned long *)0x4A000008)
  45. #define PRIORITY (*(volatile unsigned long *)0x4A00000c)
  46. #define INTPND (*(volatile unsigned long *)0x4A000010)
  47. #define INTOFFSET (*(volatile unsigned long *)0x4A000014)
  48. #define SUBSRCPND (*(volatile unsigned long *)0x4A000018)
  49. #define INTSUBMSK (*(volatile unsigned long *)0x4A00001c)
  50.  
  51. /*external interrupt registers*/
  52. #define EINTMASK (*(volatile unsigned long *)0x560000a4)
  53. #define EINTPEND (*(volatile unsigned long *)0x560000a8)
  54.  
  55. /*clock registers*/
  56. #define LOCKTIME (*(volatile unsigned long *)0x4c000000)
  57. #define MPLLCON (*(volatile unsigned long *)0x4c000004)
  58. #define UPLLCON (*(volatile unsigned long *)0x4c000008)
  59. #define CLKCON (*(volatile unsigned long *)0x4c00000c)
  60. #define CLKSLOW (*(volatile unsigned long *)0x4c000010)
  61. #define CLKDIVN (*(volatile unsigned long *)0x4c000014)
  62.  
  63. /*PWM & Timer registers*/
  64. #define TCFG0 (*(volatile unsigned long *)0x51000000)
  65. #define TCFG1 (*(volatile unsigned long *)0x51000004)
  66. #define TCON (*(volatile unsigned long *)0x51000008)
  67. #define TCNTB0 (*(volatile unsigned long *)0x5100000c)
  68. #define TCMPB0 (*(volatile unsigned long *)0x51000010)
  69. #define TCNTO0 (*(volatile unsigned long *)0x51000014)
  70.  
  71. #define GSTATUS1 (*(volatile unsigned long *)0x560000B0)

  serial.h

  1. void uart0_init(void);
  2. void putc(unsigned char c);
  3. unsigned char getc(void);
  4. int isDigit(unsigned char c);
  5. int isLetter(unsigned char c);

  head.S

  1. @******************************************************************************
  2. @ Filehead.S
  3. @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
  4. @******************************************************************************
  5.  
  6. .extern main
  7. .text
  8. .global _start
  9. _start:
  10. Reset:
  11. ldr sp, = @ 设置栈指针,以下都是C函数,调用前需要设好栈
  12. bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
  13. bl clock_init @ 设置MPLL,改变FCLKHCLKPCLK
  14. bl memsetup @ 设置存储控制器以使用SDRAM
  15. bl copy_steppingstone_to_sdram @ 复制代码到SDRAM
  16. ldr pc, =on_sdram @ 跳到SDRAM中继续执行
  17. on_sdram:
  18. ldr sp, =0x34000000 @ 设置栈指针
  19. ldr lr, =halt_loop @ 设置返回地址
  20. ldr pc, =main @ 调用main函数
  21. halt_loop:
  22. b halt_loop

  init.c

  1. /*
  2. * init.c: 进行一些初始化
  3. */
  4.  
  5. #include "s3c24xx.h"
  6.  
  7. void disable_watch_dog(void);
  8. void clock_init(void);
  9. void memsetup(void);
  10. void copy_steppingstone_to_sdram(void);
  11.  
  12. /*
  13. * 关闭WATCHDOG,否则CPU会不断重启
  14. */
  15. void disable_watch_dog(void)
  16. {
  17. WTCON = ; // 关闭WATCHDOG很简单,往这个寄存器写0即可
  18. }
  19.  
  20. #define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
  21. #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
  22. /*
  23. * 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
  24. * 有如下计算公式:
  25. * S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)
  26. * S3C2440: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
  27. * 其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
  28. * 对于本开发板,Fin = 12MHz
  29. * 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,
  30. * FCLK=200MHz,HCLK=100MHz,PCLK=50MHz
  31. */
  32. void clock_init(void)
  33. {
  34. // LOCKTIME = 0x00ffffff; // 使用默认值即可
  35. CLKDIVN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
  36.  
  37. /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
  38. __asm__(
  39. "mrc p15, 0, r1, c1, c0, 0\n" /* 读出控制寄存器 */
  40. "orr r1, r1, #0xc0000000\n" /* 设置为“asynchronous bus mode” */
  41. "mcr p15, 0, r1, c1, c0, 0\n" /* 写入控制寄存器 */
  42. );
  43.  
  44. /* 判断是S3C2410还是S3C2440 */
  45. if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
  46. {
  47. MPLLCON = S3C2410_MPLL_200MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
  48. }
  49. else
  50. {
  51. MPLLCON = S3C2440_MPLL_200MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
  52. }
  53. }
  54.  
  55. /*
  56. * 设置存储控制器以使用SDRAM
  57. */
  58. void memsetup(void)
  59. {
  60. volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
  61.  
  62. /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
  63. * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
  64. * SDRAM之前就可以在steppingstone中运行
  65. */
  66. /* 存储控制器13个寄存器的值 */
  67. p[] = 0x22011110; //BWSCON
  68. p[] = 0x00000700; //BANKCON0
  69. p[] = 0x00000700; //BANKCON1
  70. p[] = 0x00000700; //BANKCON2
  71. p[] = 0x00000700; //BANKCON3
  72. p[] = 0x00000700; //BANKCON4
  73. p[] = 0x00000700; //BANKCON5
  74. p[] = 0x00018005; //BANKCON6
  75. p[] = 0x00018005; //BANKCON7
  76.  
  77. /* REFRESH,
  78. * HCLK=12MHz: 0x008C07A3,
  79. * HCLK=100MHz: 0x008C04F4
  80. */
  81. p[] = 0x008C04F4;
  82. p[] = 0x000000B1; //BANKSIZE
  83. p[] = 0x00000030; //MRSRB6
  84. p[] = 0x00000030; //MRSRB7
  85. }
  86.  
  87. void copy_steppingstone_to_sdram(void)
  88. {
  89. unsigned int *pdwSrc = (unsigned int *);
  90. unsigned int *pdwDest = (unsigned int *)0x30000000;
  91.  
  92. while (pdwSrc < (unsigned int *))
  93. {
  94. *pdwDest = *pdwSrc;
  95. pdwDest++;
  96. pdwSrc++;
  97. }
  98. }

  serial.c

  1. #include "s3c24xx.h"
  2. #include "serial.h"
  3.  
  4. #define TXD0READY (1<<2)
  5. #define RXD0READY (1)
  6.  
  7. #define PCLK 50000000 // init.c中的clock_init函数设置PCLK为50MHz
  8. #define UART_CLK PCLK // UART0的时钟源设为PCLK
  9. #define UART_BAUD_RATE 115200 // 波特率
  10. #define UART_BRD ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)
  11.  
  12. /*
  13. * 初始化UART0
  14. * 115200,8N1,无流控
  15. */
  16. void uart0_init(void)
  17. {
  18. GPHCON |= 0xa0; // GPH2,GPH3用作TXD0,RXD0
  19. GPHUP = 0x0c; // GPH2,GPH3内部上拉
  20.  
  21. ULCON0 = 0x03; // 8N1(8个数据位,无较验,1个停止位)
  22. UCON0 = 0x05; // 查询方式,UART时钟源为PCLK
  23. UFCON0 = 0x00; // 不使用FIFO
  24. UMCON0 = 0x00; // 不使用流控
  25. UBRDIV0 = UART_BRD; // 波特率为115200
  26. }
  27.  
  28. /*
  29. * 发送一个字符
  30. */
  31. void putc(unsigned char c)
  32. {
  33. /* 等待,直到发送缓冲区中的数据已经全部发送出去 */
  34. while (!(UTRSTAT0 & TXD0READY));
  35.  
  36. /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
  37. UTXH0 = c;
  38. }
  39.  
  40. /*
  41. * 接收字符
  42. */
  43. unsigned char getc(void)
  44. {
  45. /* 等待,直到接收缓冲区中的有数据 */
  46. while (!(UTRSTAT0 & RXD0READY));
  47.  
  48. /* 直接读取URXH0寄存器,即可获得接收到的数据 */
  49. return URXH0;
  50. }
  51.  
  52. /*
  53. * 判断一个字符是否数字
  54. */
  55. int isDigit(unsigned char c)
  56. {
  57. if (c >= '' && c <= '')
  58. return ;
  59. else
  60. return ;
  61. }
  62.  
  63. /*
  64. * 判断一个字符是否英文字母
  65. */
  66. int isLetter(unsigned char c)
  67. {
  68. if (c >= 'a' && c <= 'z')
  69. return ;
  70. else if (c >= 'A' && c <= 'Z')
  71. return ;
  72. else
  73. return ;
  74. }

  main.c

  1. #include "serial.h"
  2.  
  3. int main()
  4. {
  5. unsigned char c;
  6. uart0_init(); // 波特率115200,8N1(8个数据位,无校验位,1个停止位)
  7.  
  8. while()
  9. {
  10. // 从串口接收数据后,判断其是否数字或子母,若是则加1后输出
  11. c = getc();
  12. if (isDigit(c) || isLetter(c))
  13. putc(c+);
  14. }
  15.  
  16. return ;
  17. }

七、UART的更多相关文章

  1. am335x system upgrade kernel uart(七)

    1      Scope of Document This document describes UART hardware design, uart driver porting 2      Re ...

  2. UART

    一.协议部分: 协议部分转自:http://www.s8052.com/index.htm 串行通信的传送方向通常有三种: 1.为单工,只允许数据向一个方向传送: 2.半双工,允许数据向两个方向中的任 ...

  3. [ZigBee] 13、ZigBee基础阶段性回顾与加深理解——用定时器1产生PWM来控制LED亮度(七色灯)

    引言:PWM对于很多软件工程师可能又熟悉又陌生,以PWM调节LED亮度为例,其本质是在每个周期都偷工减料一些,整体表现出LED欠压亮度不同的效果.像大家看到的七色彩灯其原理也类似,只是用3路PWM分别 ...

  4. 【转】Android bluetooth介绍(二): android blueZ蓝牙代码架构及其uart 到rfcomm流程

    原文网址:http://blog.sina.com.cn/s/blog_602c72c50102uzoj.html 关键词:蓝牙blueZ  UART  HCI_UART H4  HCI  L2CAP ...

  5. v3学院带你一次性认清UART、RS-232、RS-422、RS-485的区别

    通讯问题,和交通问题一样,也有高速.低速.拥堵.中断等等各种情况.如果把串口通讯比做交通,UART比作车站,那么一帧的数据就好比汽车.汽车跑在路上,要遵守交通规则.如果是市内,一般限速30.40,而高 ...

  6. 八、mini2440裸机程序之UART(1)简单介绍【转】

    转自:http://blog.csdn.net/shengnan_wu/article/details/8298869 一.概述          S3C2440通用异步接收和发送(UART)提供了三 ...

  7. SAM4E单片机之旅——8、UART初步

    通信还是比让LED灯闪烁实用得多的. 这次试试使用UART,实现开发版和PC间的通信.功能比较简单,就是把PC发向开发版的内容发送回去.这次主要介绍一下UART的配置,至于通信,则使用较为简单的不断查 ...

  8. Android bluetooth介绍(两): android 蓝牙源架构和uart 至rfcomm过程

    关键词:蓝牙blueZ  UART  HCI_UART H4  HCI  L2CAP RFCOMM  版本号:基于android4.2先前版本 bluez内核:linux/linux3.08系统:an ...

  9. C与ARM汇编结合实现mini2440串口uart简单程序

    最近学完了ARM的一些基础知识,开始在mini2440上开发一些简单的程序,串口发送程序是一开始涉及多个寄存器的例子,稍有繁多的步骤应该是开发过程中要慢慢适应的境况 下面的程序的目的是实现mini24 ...

随机推荐

  1. centos 7 修改系统屏幕分辨率

    centos 7 修改系统屏幕分辨率,命令方式和图形方式的修改方法. 命令:xrandr 通过命令 xrandr 修改系统的分辨率,输入xrandr: bash [admin@localhost ~] ...

  2. linux学习之centos(三):mysql数据库的安装和配置

    前言:mysql简介 说到数据库,我们大多想到的是关系型数据库,比如mysql.oracle.sqlserver等等,这些数据库软件在windows上安装都非常的方便,在Linux上如果要安装数据库, ...

  3. 我终于激活Windows Server2008 R2了!!

    经过我不懈的努力,在重装两次系统后,我终于实现了win2008的KMS激活.这个方法可以避免虚拟机架设KMS服务器的麻烦.现将激活方法发布如下. 首先要选择安装的操作系统.Windows Server ...

  4. 网页性能优化之异步加载js文件

    一个网页的有很多地方可以进行性能优化,比较常见的一种方式就是异步加载js脚本文件.在谈异步加载之前,先来看看浏览器加载js文件的原理. 浏览器加载 JavaScript 脚本,主要通过<scri ...

  5. html5 视频和音频

    视频:html5支持视屏文件或者视屏流. html5使用video元素来播放视屏,支持的类型有OGG,MEPG 4,webM,但是不同的浏览器支持类型不同. src可以放置视屏文件的路径,可以使用元素 ...

  6. 封装caffe版的deeplab为库供第三方使用

    1.解决deeplab编译问题 http://m.2cto.com/kf/201612/579545.html

  7. docker--Dockerfile--java

    # AlpineLinux with a glibc-2.26-r0 and Oracle Java 7FROM alpine:3.6 MAINTAINER Anastas Dancha <an ...

  8. Codeforces Round #381 (Div. 2)C Alyona and mex

    Alyona's mother wants to present an array of n non-negative integers to Alyona. The array should be ...

  9. MT【207】|ax^2+bx+c|中判别式$\Delta$的含义

    已知$a,b\in R^+,a+b=2$且对任意的$x\in R$,均有$|2x^2+ax-b|\ge|x^2+cx+d|$则$\dfrac{d-4c}{cd}$的最小值______ 提示:注意到$\ ...

  10. Shell基础知识(二)

    对于一个shell脚本来说,第一行是 "#!/bin/bash",这条命令中的 "#!" 告诉系统该用哪一款解释器来对该脚本进行解释,后面的"/bin ...