s3c2440-裸机篇-06|uart数据发送接收实验(扫描模式)(代码片段)

Neutionwei Neutionwei     2022-12-04     543

关键词:

关于RS-232C串口总线通信标准请参见我的另一个系列专题文章:
【嵌入式系统通信协议②】EIA RS-232C串口总线标准

实验 —— UART数据收发实验

1. 看原理图确定UART硬件如何连接



由原理图可以看出,JZ2440开发板上将三个串口全部引出,其中UART0设置了板载的USB转串口电路,只需连接板上的USB口就可以,所以接下来我们使用UART0进行数据收发实验。

2. 看芯片手册设置引脚复用功能(GPHCON)、开启片内上拉(GPHUP)

由原理图可以看出,UART0的引脚是:

  • GPH2:TXD0
  • GPH3:RXD0

这两个引脚都是普通的GPIO口,所以需要设置引脚复用功能,作为串口UART0的引脚:

在【【嵌入式系统通信协议②】EIA RS-232C串口总线标准】一文中讲解通信协议的时候讲过,串口的两根信号线在空闲的时候需要保持高电平,所以要开启这两个引脚的片内上拉电阻:

3. 看芯片手册设置串口

3.1.设置串口数据帧格式(ULCONn)

3.2.设置串口(UCONn)

3.2.1.设置串口波特率产生器的时钟源([11:10])

之前在【【S3C2440⑤】S3C2440时钟体系】中进行实验设置了时钟PCLK=50Mhz,所以在此基础上选择PCLK作为串口UART0的波特率发生器的时钟来源:

3.2.2.设置发送/接收数据模式([3:0])

为了简单起见,不使用中断模式和DMA模式,直接采用查询模式(polling mode):

3.3.设置波特率(UBRDIVn)


波特率由UBRDIVn寄存器决定,这个寄存器的值该取多少呢?公式如下:

比如,这里PCLK = 50Mhz,想要设置波特率为115200bit/s

UBRDIVn = (int)(50000000/(115200*16)) - 1
		= (int)(50000000/1843200) - 1
		= (int)(27.13) - 1
		= 27 - 1
		= 26

3.4.数据发送/接收缓存寄存器(UTXHn和URXHn)


其中最重要的是,在使用指针访问这个寄存器的时候,不能使用int型指针,因为int型指针访问的是4个字节的数据,而此处只能访问一个字节数据,所以要使用char型指针

#define UTXH0	(*(volatile unsigned char *)(0x50000020))  //UART 0 transmission hold 
#define URXH0	(*(volatile unsigned char *)(0x50000024))  //UART 0 receive buffer    

3.5.发送/接收状态寄存器

4. 编写代码

4.1.启动文件start.s

和之前相同。

4.2.驱动文件bsp_uart_scan.c/bsp_uart_scan.h

  • bsp_uart_scan.h
#ifndef _BSP_UART_SCAN_H_
#define _BSP_UART_SCAN_H_

void uart0_init();
int putchar(int c);
int getchar(void);
int puts(const char *s);

#endif /* BSP_UART_SCAN_H */

  • bsp_uart_scan.c
/**
 * @ file    bsp_uart_scan.c
 * @ breif   uart0驱动
 * @ note    查询方式
 * @ author  mculover666
 * @ date    2019/3/7
*/
# include "bsp_uart_scan.h"
# include "s3c2440.h"
/**
 * @ brief  串口0初始化
 * @ param  无
 * @ retval 无
 * @ note   115200,8N1
*/
void uart0_init()

    /* 初始化uart0使用的引脚 */
    //GPH2-TXD0,GPH3-RXD0
    GPHCON &= ~(3<<(2*2) | (3<<(2*3)));
    GPHCON |= (2<<(2*2)) | (2<<(2*3));
    //开启GPH2、GPH3上拉    
    GPHUP  &= ~((1<<2) | (1<<3));
    /* 设置数据格式: 8N1 */
    ULCON0 = 0x03;
    /* 设置串口 */
    // 使用PCLK作为串口时钟源,发送和接收均为查询模式
    UCON0 = 0x0005;
    /* 设置波特率为115200bit/s(PCLK = 50Mhz) */
    //UBRDIVn = (int)(50000000/(115200*16)) - 1 = 26
    UBRDIV0 = 26;

/**
 * @ brief  串口发送一个字节的数据
 * @ param  c-要发送的数据
 * @ retval 无
 * @ note   映射到串口0
*/
int putchar(int c)

    /* 在发送数据之前检查是否处于发送完成状态 */
    while(!(UTRSTAT0 & 0x06));
    UTXH0 = (unsigned char)c;
    return 0;

/**
 * @ brief  串口接收一个字节的数据
 * @ param  无
 * @ retval int
 * @ note   映射到串口0
*/
int getchar(void)

    while (!(UTRSTAT0 & (0x01)));
	return URXH0;

/**
 * @ brief  串口发送字符串
 * @ param  s
 * @ retval 无
 * @ note   映射到串口0
*/
int puts(const char *s)

    while(*s)
    
        putchar(*s);
        s++;
    
    return 0;

/* 实现printf */
#if 1
#include <stdio.h>
int _write(int fd, char *ptr, int len)  
  
    while(*ptr)
    
        while(!(UTRSTAT0 & 0x06));
        UTXH0 = (unsigned char)(*ptr++);
    
  return len;

#endif

4.3.驱动测试文件main.c

/**
 * @ breif   测试uart0驱动程序:bsp_uart_scan.c
 * @ author  mculover666
 * @ date    2019/3/7
*/
# include "bsp_uart_scan.h"
int main(void)

    unsigned char recv_data;
    //初始化uar0:115200,8N1
    uart0_init();
    //测试发送字符串
    puts("Hello,World.I am mculover666.\\r\\n");
    //测试printf
    printf("printf is ok.\\r\\n");
    while(1)
    
        recv_data = getchar();
        putchar(recv_data);
    

5. 编译代码

使用makefile构建编译,在之前的基础上进行修改,如下:

TARGET = uart
CFLAGS = -Wall	#输出所有warning
$(TARGET).bin:$(TARGET).elf
	arm-linux-objcopy -O binary -S $(TARGET).elf $(TARGET).bin
#注意:启动文件必须第一个链接
$(TARGET).elf:start.o bsp_uart_scan.o main.o
	arm-linux-ld -Ttext 0 start.o bsp_uart_scan.o main.o -o $(TARGET).elf
start.o:start.s
	arm-linux-gcc -c start.s $(CFLAGS) -o start.o
bsp_uart_scan.o:bsp_uart_scan.c
	arm-linux-gcc -c bsp_uart_scan.c $(CFLAGS) -o bsp_uart_scan.o
main.o:main.c
	arm-linux-gcc -c main.c $(CFLAGS) -o main.o	
clean:
	rm -rf *.o *.elf *.bin
download_to_nand:
	#下载到nand flash
	oflash 0 1 0 0 0 $(TARGET).bin 

6. 下载运行

这里使用SerialPort Utility软件进行测试:

7.实验总结

历经三天,终于完成了本实验,通过该实验:

  • 嵌入式系统的角度来说:掌握了RS-232C串口总线通信标准,包括其物理层和协议层,针对现在的情况主要使用其改进版,它的协议简单,在嵌入式系统中被大量使用,但是也有缺点,就是传输距离短,在15m左右;
  • S3C2440这颗芯片来说:掌握了其UART设备的使用。

s3c2440-裸机篇-07|s3c2440内存控制器(memorycontroller)

1.作用S3C2440的内存控制器作用是:负责向外部扩展的存储类设备提供控制信号。内存控制器支持的外部扩展存储类设备有:SRAMSDRAMNorFlash网卡DMA9000(类存储设备)内存控制器不支持nandflash,S3C2440提供了独立的n... 查看详情

mini2440裸机试炼之——uart与pc端实现文件字符传输

1、?波特率(Baudrate)即调制速率,1波特即指每秒传输1个符号。2、?非FIFO模式,即数据传输不利用FIFO缓存,一个字节一个字节地传输。3、?接收到的数据是放到接收缓存器URXHn中。要发送数据时,是把数据放入发送缓存器UTXHn中... 查看详情

_embedded-system专栏文章导航与优秀笔记整理(2021.08.08更新)

一、ARM裸机篇1、Mculover666博主基于JZ2440板卡的S3C2440裸机开发笔记:S3C2440-裸机篇-01|JZ2440开发板快速上手S3C2440-裸机篇-02|安装和使用arm-linux-gcc交叉编译工具链S3C2440-裸机篇-03|GPIO的使用(点亮LED、按键检测)S3C2440-裸机... 查看详情

s3c2440-裸机篇-09|使用s3c2440操作norflash(代码片段)

1.NorFlash与NandFlashNorNand接口引脚多,类似于RAM引脚较少容量小(1-32MB)大(128-512MB)读操作简单,和RAM相同简单,和RAM相同写操作发出特定命令才能写入发出特定命令才能写入价格贵便宜比较无坏块有... 查看详情

s3c2440-裸机篇-10|使用s3c2440操作nandflash(代码片段)

1.NorFlash与NandFlashNorNand接口引脚多,类似于RAM引脚较少容量小(1-32MB)大(128-512MB)读操作简单,和RAM相同简单,和RAM相同写操作发出特定命令才能写入发出特定命令才能写入价格贵便宜比较无坏块有... 查看详情

s3c2440-裸机篇-08|使用s3c2440操作sdram(配置内存控制器)(代码片段)

1.前言提起SDRAM,大家都会觉得太难了,要编程写出SDRAM的控制时序更是难上加难,对的,没错!一年前我也是这样想的,学习这一节内容的时序觉得非常难,视频看了好几遍不太懂,对于SDRAM的控制... 查看详情

第11课.串口(uart)的使用(代码片段)

1.UART连线图S3C2440有3个独立通道的UART2.数据传输流程1.平时数据线处于“空闲”状态(1状态)2.当要发送数据时,UART改变TxD数据线的状态(变为0状态),并维持1位的时间,这样接收方检测到开始位后,在等待1.5位的时间就开始... 查看详情

jz2440裸机驱动第13章lcd控制器

本章目标 了解LCD显示器的接口及时序;掌握S3C2410/S3C2440LCD控制器的使用方法;了解帧缓冲区的概念,掌握如何设置帧缓冲区来显示图像;13.1LCD和LCD控制器13.1.1LCD显示器1.LCD的种类2.LCD的接口  CPU或显卡发出的图像数据... 查看详情

mini2440裸机开发之串口uart(代码片段)

一、S3C2440上的UART1.1串口概述串口的使用位于S3C2440芯片手册的第11章。S3C2440A的通用异步收发器(UART)配有3个独立异步串行I/O端口,每个都可以是基于中断或基于DMA模式的操作。换句话说,UART可以通过产生中断或DMA请求来进行CP... 查看详情

s3c2440裸机开发通用异步收发器uarn

四、通用异步收发器UARN原文地址http://blog.csdn.net/woshidahuaidan2011/article/details/51137047byjaosnEmail:[email protected] UART(UniversalAsynchronousReceiver/Transmitter。通用异步接收/发送装置)用于异步通信。能够实现全双工发送和接收 查看详情

jz2440裸机驱动第6章存储控制器

本章目标:  了解S3C2410/S3C2440地址空间的布局  掌握如何通过总线形式访问扩展的外设,比如内存、NORFlash、网卡等·································································... 查看详情

tq2440开发板学习纪实---基于中断的uart串口接收

UART0的发送、接收、错误分别产生不同的中断,可以分别控制。本文仅对UART0的接收采用中断方式,发送仍然采用轮训方式。这样有个很大的用处,那就是程序陷入死循环是,可以通过UART0发送给ARM一个信号,... 查看详情

jz2440裸机驱动第10章系统时钟和定时器

本章目标    了解S3C2410/S3C2440的时钟体系结构   掌握通过设置MPLL改变系统时钟的方法   掌握在不同的频率下设置存储控制器的方法   掌握PWM定时器的用法   了解WATCHDOG定... 查看详情

s3c2440裸机-lcd编程(实现显示功能)(代码片段)

1.让LCD显示满屏红色我们想要在LCD上显示出数据,所需步骤如下:a.初始化LCDb.使能LCDc.获取LCD参数:fb_base,xres,yres,bppd.往framebuffer中写数据所需步骤如下:1.初始化LCD工作我们在前面一节框架准备和LCD初始化已经详细介绍了。2.使能L... 查看详情

jz2440裸机驱动第7章内存管理单元mmu

本章目标:  了解虚拟地址和物理地址的关系;  掌握如何通过设置MMU来控制虚拟地址到物理地址的转化;  了解MMU的内存访问权限机制;  了解TLB、Cache、Writebuffer的原理,使用时的注意事项; &n... 查看详情

arm裸机开发:串口通信(代码片段)

文章目录ARM裸机开发:串口通信一、硬件平台:二、原理分析2.1UART介绍2.2UART寄存器2.3UART使用步骤三、程序编写四、实验现象ARM裸机开发:串口通信一、硬件平台:正点原子I.MX6U阿尔法开发板二、原理分析2.1UART介... 查看详情

uart接收和发送数据

uart异步接收数据的时候,总是无法接收完整的字符串,通过网上查找,串口接收和发送都是一个个字节进行。功能:通过串口调试工具往串口发送数据,然后在接收完整的数据后再将数据发给电脑。问题如下:1.串口在接收数据... 查看详情

mini2440裸机开发之中断控制器(代码片段)

一、S3C2440上的中断1.1中断概述S3C2440A中的中断控制器接受来自60个中断源的请求。提供这些中断源的是内部外设,如DMA控制器、UART、IIC等等。在这些中断源中,UARTn、AC97和EINTn中断对于中断控制器而言是“或”关系。当从内部外... 查看详情