linux裸机串口,裸机系列-UART串口
下面我们就给出如何用s3c2440来实现非FIFO的UART通信。要实现某种通信,就必须遵循该通信协议。UART的协议包括传输数据的位数,停止位的位数,以及是否进行奇偶校验,这些设置是利用ULCONn寄存器完成的。另一个很重要的地方就是设置波特率。s3c2440波特率的时钟源有三个:PCLK、FCLK/n和UEXTCLK。时钟源的选择是由UCONn的第10位和第11位来完成的。波特率的具体计算公式为:
时钟源频率÷(波特率×16)-1
这个计算结果很可能是小数,把该小数取最接近的整数,放入寄存器UBRDIVn中就完成了波特率的设置。如我们选择波特率的时钟源为PCLK,它为50MHz,我们设置的波特率为115.2kHz,通过上式计算的结果为26.13,取整后得到26,那么我们把26放入UBRDIVn中即可。由于我们没有使用FIFO和MODEM,所以可以不用设置FIFO控制寄存器UFCONn和MODEM控制寄存器UMCONn。通过以上寄存器的设置,UART就可以正常传输数据。
接收到的数据是放到接收缓存器URXHn中,要发送数据时,是把数据放入发送缓存器UTXHn中。由于UART是通过字节方式传输数据的,因此要区分是大端模式还是小端模式,也就是说这两个寄存器在这两种模式下,所在的地址是不同。为了了解当前数据传输的各种状态,还需要一些状态寄存器。传输状态寄存器UTRSTATn非常有用,它的第0位可以用来判断接受缓存器内是否有可接收的数据,第1位和第2位可以用来判断发送缓存器中是否为空,为空时可以发送数据。由于在这里我们不进行传输数据时错误的判断,因此错误状态寄存器UERSTATn不需要,FIFO状态寄存器UFSTATn和MODEM状态寄存器UMSTATn在这里也不需要。
我们给出UART通信的两种方法:查询和中断。为了验证程序,使用任一款的串行通信软件来实现PC和s3c2440之间的通信即可。
首先给出的是查询程序。它是在主程序的循环体内不断查询UART端口,当有数据来时,就接收数据,并再通过UART发送该数据。然后根据所接收数据的不同,分别执行不同的内容,如点亮、熄灭LED,蜂鸣器响、或不响。在这里,我们每次只完成一个字节的传输。
#define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
#define rGPHCON (*(volatile unsigned *)0x56000070) //Port H control
#define rGPHUP (*(volatile unsigned *)0x56000078) //Pull-up control H
#define rULCON0 (*(volatile unsigned *)0x50000000) //UART 0 Line control
#define rUCON0 (*(volatile unsigned *)0x50000004) //UART 0 Control
#define rUFCON0 (*(volatile unsigned *)0x50000008) //UART 0 FIFO control
#define rUMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) //UART 0 Rx error status
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) //UART 0 FIFO status
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) //UART 0 Modem status
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor
//little endian
#define rUTXH0 (*(volatile unsigned char *)0x50000020) //UART 0 Transmission Hold
#define rURXH0 (*(volatile unsigned char *)0x50000024) //UART 0 Receive buffer
void Main(void)
{
char ch;
rGPBCON = 0x015551;
rGPBUP = 0x7ff;
rGPBDAT = 0x1e0;
rGPHCON = 0x00faaa; //使用UART0功能
rGPHUP = 0x7ff;
rULCON0 = 0x3; //设置UART0无奇偶校验,一位停止位,8位数据
rUCON0 = 0x245; //PCLK为时钟源,接收和发送数据为查询或中断方式
rUFCON0 = 0; //
rUMCON0 = 0; //
rUBRDIV0 = 26; //设置波特率,PCLK为50MHz,波特率为115.2kHz
while(!(rUTRSTAT0 & 0x2)); //等待并判断发送缓存是否为空
rUTXH0 = 0xaa; //是空,则发送0xAA字节
while(1)
{
while(!(rUTRSTAT0 & 0x1)); //等待并判断接收缓存是否准备好
ch = rURXH0; //接收一个字节数据
while(!(rUTRSTAT0 & 0x2)); //等待并判断发送缓存是否为空
rUTXH0 = ch; //发送一个字节数据
switch(ch) //根据所接收数据的不同,执行不同的程序
{
case 0x11: //灭LED
rGPBDAT |= 0x1e0;
break;
case 0x22: //亮LED
rGPBDAT &= 0x1f;
break;
case 0x33: //蜂鸣器不响
rGPBDAT &= 0x1e0;
break;
case 0x44: //蜂鸣器响
rGPBDAT |= 0x1;
break;
default: //LED灭,蜂鸣器不响
rGPBDAT = 0x1e0;
break;
}
}
}
下面是UART中断程序,它要比查询复杂一些,因为涉及到了中断处理,并且UART发送数据和接收数据是一个中断源。主程序循环体内不执行任何程序,都在UART中断程序内执行。当接收到0x55字节数据时,亮两个LED,当接收到其他数据时,发送该字节,并在发送部分执行亮4个LED程序。
#define _ISR_STARTADDRESS 0x33ffff00
#define pISR_UART0 (*(unsigned *)(_ISR_STARTADDRESS+0x90))
#define U32 unsigned int
#define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
#define rGPHCON (*(volatile unsigned *)0x56000070) //Port H control
//#define rGPHDAT (*(volatile unsigned *)0x56000074) //Port H data
#define rGPHUP (*(volatile unsigned *)0x56000078) //Pull-up control H
#define rULCON0 (*(volatile unsigned *)0x50000000) //UART 0 Line control
#define rUCON0 (*(volatile unsigned *)0x50000004) //UART 0 Control
#define rUFCON0 (*(volatile unsigned *)0x50000008) //UART 0 FIFO control
#define rUMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) //UART 0 Rx error status
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) //UART 0 FIFO status
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) //UART 0 Modem status
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor
//little endian
#define rUTXH0 (*(volatile unsigned char *)0x50000020) //UART 0 Transmission Hold
#define rURXH0 (*(volatile unsigned char *)0x50000024) //UART 0 Receive buffer
#define rSRCPND (*(volatile unsigned *)0x4a000000) //Interrupt request status
#define rINTMSK (*(volatile unsigned *)0x4a000008) //Interrupt mask control
#define rINTPND (*(volatile unsigned *)0x4a000010) //Interrupt request status
#define rSUBSRCPND (*(volatile unsigned *)0x4a000018) //Sub source pending
#define rINTSUBMSK (*(volatile unsigned *)0x4a00001c) //Interrupt sub mask
void __irq uartISP(void)
{
char ch;
rSUBSRCPND |= 0x3;
rSRCPND = 0x1<<28;
rINTPND = 0x1<<28;
if(rUTRSTAT0 & 1) //接收数据处理部分
{
ch = rURXH0; //接收字节数据
if(ch==0x55)
rGPBDAT = ~0x61; //亮两个LED
else
rUTXH0 = ch; //发送字节数据
}
else //发送数据处理部分
{
rGPBDAT = ~0x1e1; //亮4个LED
}
}
void Main(void)
{
rGPBCON = 0x015551;
rGPBUP = 0x7ff;
rGPBDAT = 0x1e0;
rGPHCON = 0x00faaa;
rGPHUP = 0x7ff;
rULCON0 = 0x3;
rUCON0 = 0x5;
rUFCON0 = 0;
rUMCON0 = 0;
rUBRDIV0 = 26;
rSRCPND = 0x1<<28;
rSUBSRCPND = 0x3;
rINTPND = 0x1<<28;
rINTSUBMSK = ~(0x3); //打开UART0发送和接收中断屏蔽
rINTMSK = ~(0x1<<28); //打开UART0中断屏蔽
pISR_UART0 = (U32)uartISP;
while(1)
{
}
}
最后还要强调几点关于非FIFO模式下UART中断的一些注意事项:
1.对于s3c2440来说,接收数据是被动的,发送数据是主动的,因此一般来说,接收数据用中断方式,发送数据用查询方式较好;
2.在中断方式下,当接收到数据时,尽管可能该数据无用,但也一定要读取它,否则下次再接收数据时,不会再引起中断,因为接收数据缓存器被上次接收到的数据所霸占,只要没有读取它,它就永远在那里;
3.由于UART中断涉及到SUBSRCPND寄存器,因此在中断处理程序中不仅要清SRCPND寄存器,还要清SUBSRCPND寄存器,它们的顺序一定是先清SUBSRCPND寄存器,再清SRCPND寄存器,否则就会引起一个中断两次响应的问题。因为是否中断由SRCPND寄存器决定,而SRCPND寄存器的相关状态位由SUBSRCPND寄存器决定,如果先清SRCPND寄存器,而还没有清SUBSRCPND寄存器的话,SRCPND寄存器的相关位还是会被置1,而一旦被置1,则一定还会引起中断。
linux裸机串口,裸机系列-UART串口相关推荐
- 51单片机入门——UART串口通信
文章目录 前言 1.什么是串行通信 2. USB转串口通信 3. IO 口模拟 UART 串口通信 4 UART串口通信的基本应用 4.1 通信的三种类型 4.2 UART模块 4.3 UART 串口 ...
- 【超全面】Linux嵌入式干货学习系列教程
文章目录 一.前言 二.Linux基础篇 三.数据结构与算法基础 三.Linux应用篇 四.Linux网络篇 五.ARM篇 六.Linux系统移植篇 七.Linux驱动篇 八.Linux特别篇 九.L ...
- linux编译运行uart,嵌入式Linux裸机开发(七)——UART串口通信
嵌入式Linux裸机开发(七)--UART串口通信 一.UART串口通信简介 通用异步收发器简称UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTE ...
- Linux裸机开发|UART串口通信
UART串口通信 不管是单片机开发还是嵌入式Linux开发,串口都是最常用到的外设.可以通过串口将开发板与电脑相连,然后在电脑上通过串口调试助手来调试程序.还有很多模块,比如蓝牙.GPS.GPRS等都 ...
- Linux uart寄存器读写,Linux下读写UART串口的代码
Linux下读写UART串口的代码,从IBM Developer network上拿来的东西,操作比較的复杂,就直接跳过了,好在代码能用,记录一下- 两个实用的函数- /** *@brief 设置串口 ...
- AM335x Linux uart 串口(rs485rs232)无法正常通信的一种解决方法
先大概说说我是如何解决rs485(uart4)&rs233(uart5)的通信问题. 首先,在kernel-AGV/drivers/tty/serial/omap-serial.c中确定串口的 ...
- 嵌入式Linux 串口编程系列2--termios的VMIN和VTIME深入理解
在上一篇文章中,我们介绍了串口的一些基本知识.串口配置接口 termios结构体的概念,串口的配置参数有n多个,这里面不用都背下来,什么时候使用,翻看手册即可,但是有两个 参数是一定要理解的,就是VM ...
- 嵌入式Linux 串口编程系列3——通过VTIM、VMIN、select实现串口不定长数据接收功能
上一篇文章中,我们详细分析了VTIM和VMIN的功能, <嵌入式Linux 串口编程系列2--termios的VMIN和VTIME深入理解> 也明白了这两个参数设计的初衷和使用方法,接下来 ...
- iTop-4412 裸机程序(十三)- 串口初始化
目录 Exynos4412 串口介绍 串口框图 串口的三种常见模式 串口初始化 Exynos4412 串口介绍 见 <SEC_Exynos4412_Users Manual_Ver.1.00.0 ...
最新文章
- 目前流行的源程序版本管理软件和项目管理软件都有哪些?各有什么优缺点?...
- 小程序的事件处理参数不能取得
- python爬虫实战(一)--------中国作物种质信息网
- 图片加载之SDWebImage(上)
- 【网络流】植物大战僵尸(P2805)
- 大公司体制内创新的困境
- 向国外投稿需要注意些下面几点
- Service GIS
- PR常用的效果和转场,视频防抖、宽银幕效果、设置默认效果
- 新路由3鸡血版固件_NEWIFI3老毛子鸡血驱动版固件
- 病毒木马查杀实战第008篇:熊猫烧香之病毒查杀总结
- 软件自动化测试脚本如何写,(最新整理)自动化测试脚本编写规范
- Android Hook技术的简单实现
- 常用计算机检索算符,计算机信息检索过程中常用的检索表达式
- 利用脚手架创建vue项目时报这个错误,哪位大神帮忙解答一下,实在是找到解决办法了。万分感谢
- 微信开发学习总结(一)——微信开发环境搭建
- TCP套接口的sk_backlog接收队列
- SparkML -- LightGBM On Spark
- 基于Android的百度地图定位开发
- Ubuntu开机黑屏修复
热门文章
- Linux内核协议栈- 创建socket:__sock_create函数调用关系
- 3d旋转相册代码源码_用代码制作3d相册签到墙(附源码)
- Python项目实践:天天向上的力量
- ctp系统配套服务器,CTP系统
- js调用本地js文件(亲测)
- java实现线性回归(简单明了,适合理解)
- easyui的datagrid的使用方法
- java堆算法_用Java写算法之七:堆排序
- 计算机与兵器的相关,不知道计算机专业怎么样?是学校的精品学科吗?
- OpenShift 4 - 用KubeletConfig和ContainerRuntimeConfig分别修改集群节点的Kubelet和cri-o的配置