关于RS-232C串口总线通信标准请参见我的另一个系列专题文章(还未在公众号更新,请点击查看原文或者复制链接移步至csdn博客查看):
【嵌入式系统通信协议②】EIA RS-232C串口总线标准(https://blog.csdn.net/Mculover666/article/details/88227893)
由原理图可以看出,JZ2440开发板上将三个串口全部引出,其中UART0设置了板载的USB转串口电路,只需连接板上的USB口就可以,所以接下来我们使用UART0进行数据收发实验。
由原理图可以看出,UART0的引脚是:
GPH2
:TXD0GPH3
:RXD0这两个引脚都是普通的GPIO口,所以需要设置引脚复用功能,作为串口UART0的引脚:
在【嵌入式系统通信协议②】EIA RS-232C串口总线标准(https://blog.csdn.net/Mculover666/article/details/88227893)一文中讲解通信协议的时候讲过,串口的两根信号线在空闲的时候需要保持高电平,所以要开启这两个引脚的片内上拉电阻:
之前在【S3C2440⑤】S3C2440时钟体系(https://blog.csdn.net/Mculover666/article/details/88169727)中进行实验设置了时钟PCLK=50Mhz
,所以在此基础上选择PCLK
作为串口UART0的波特率发生器的时钟来源:
为了简单起见,不使用中断模式和DMA模式,直接采用查询模式(polling mode
):
波特率由UBRDIVn
寄存器决定,这个寄存器的值该取多少呢?公式如下:
比如,这里PCLK = 50Mhz
,想要设置波特率为115200bit/s
:
UBRDIVn = (int)(50000000/(115200*16)) - 1
= (int)(50000000/1843200) - 1
= (int)(27.13) - 1
= 27 - 1
= 26
其中最重要的是,在使用指针访问这个寄存器的时候,不能使用int型指针
,因为int型指针访问的是4个字节的数据,而此处只能访问一个字节数据,所以要使用char型指针
:
#define UTXH0 (*(volatile unsigned char *)(0x50000020)) //UART 0 transmission hold
#define URXH0 (*(volatile unsigned char *)(0x50000024)) //UART 0 receive buffer
和之前相同。
#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_ */
/**
* @ 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;
}
/**
* @ 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");
while(1)
{
recv_data = getchar();
putchar(recv_data);
}
}
使用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
这里使用SerialPort Utility
软件进行测试:
历经三天,终于完成了本实验,通过该实验: