第五站,我想对社会说——uart串口程序分析
来源:互联网 发布:淘宝店转让风险大吗 编辑:程序博客网 时间:2024/06/15 07:55
第五站,我想对社会说——uart串口程序分析
![](http://b1.qzone.qq.com/ac/b.gif)
我们存在的价值,是得到这个世界的认可,是让世界认识你,知道你的存在,我们内心的故事,也需要向别人倾述,否则谁能轻易了解你?我们的苦闷也需要偶尔的牢骚,如果我们与世界失去了联系和交际,简直太过单调。那么,就让我们通过UART去倾听ARM的内心吧。
6410提供了四个独立的异步串行I/O端口,每个一步串行I/O端口通过终端或者直接存储器存取(DMA)模式来操作。换句话说就是UART通过产生中断或DMA请求在CPU和UART之间传输数据.
每个UART的通道包含了连个64字节收发FIFO存储器。
每个UART包含一个波特率发生器,发送器,接收器和控制单元,该波特率发生器由PCLK,ext_uclk0或ext_uclk1进行时钟控制。
发射器和接收器包含64字节的FIFO存储器和数据移位寄存器,发送数据之前,首先将数据写入FIFO存储器,然后复制到发送移位寄存器,通过发送数据的引脚(txdn)将数据发送,
同时,通过数据接收的引脚(rsdn)将接收到的数据从接收移位寄存器复制到FIFO存储器。这其中的复制,无需要我们人工干涉,硬件自动完成。
每个UART的通道包含了连个64字节收发FIFO存储器。
每个UART包含一个波特率发生器,发送器,接收器和控制单元,该波特率发生器由PCLK,ext_uclk0或ext_uclk1进行时钟控制。
发射器和接收器包含64字节的FIFO存储器和数据移位寄存器,发送数据之前,首先将数据写入FIFO存储器,然后复制到发送移位寄存器,通过发送数据的引脚(txdn)将数据发送,
同时,通过数据接收的引脚(rsdn)将接收到的数据从接收移位寄存器复制到FIFO存储器。这其中的复制,无需要我们人工干涉,硬件自动完成。
我们要做的,就只是设置好波特率等工作,然后将数据写进发送FIFO,硬件自动会拷贝数据到发送移位寄存器发送我们的数据,读数据只需要当接收完成我们读取接收FIFO中的数据就可以了。
regs.h:
#ifndef __REGS_H#define __REGS_H/******************uart****************/#define GPACON (*(volatile unsigned int *)0x7F008000)#define ULCON0 (*(volatile unsigned int *)0x7F005000) //UART通道0行控制寄存器#define UCON0 (*(volatile unsigned int *)0x7F005004) //UART通道0控制寄存器#define UFCON0 (*(volatile unsigned int *)0x7F005008) //UART通道0FIFO控制寄存器#define UMCON0 (*(volatile unsigned int *)0x7F00500C) //UART通道0调制解调器(Modem)控制寄存器#define UTRSTAT0 (*(volatile unsigned int *)0x7F005010) //UART通道0发送/接收状态寄存器#define UERSTAT0 (*(volatile unsigned int *)0x7F005014) //UART通道0接收错误状态寄存器#define UFSTAT0 (*(volatile unsigned int *)0x7F005018) //UART通道0FIFO状态寄存器#define UMSTAT0 (*(volatile unsigned int *)0x7F00501C) //UART通道0调制解调器(Modem)状态寄存器#define UTXH0 (*(volatile unsigned int *)0x7F005020) //UART通道0发送缓冲寄存器#define URXH0 (*(volatile unsigned int *)0x7F005024) //UART通道0接收缓冲寄存器#define UBRDIV0 (*(volatile unsigned int *)0x7F005028) //UART通道0波特率分频寄存器#define UDIVSLOT0 (*(volatile unsigned int *)0x7F00502C) //UART通道0分频插槽寄存器#define UINTP0 (*(volatile unsigned int *)0x7F005030) //UART通道0中断处理寄存器#define UINTSP0 (*(volatile unsigned int *)0x7F005034) //UART通道0中断源处理器#define UINTM0 (*(volatile unsigned int *)0x7F005038) //UART通道0中断屏蔽寄存器#endif
uart.c:
#include "common.h"
#include "regs.h"
#include <stdarg.h>
/*va_list
*va_start
*va_end
*va_arg
*/
/*检查上次数据是否发完,参考S3C6410手册P1096*/
#define TR_BUSY while(!(UTRSTAT0 & 2)) //检测UTRSTAT0的第二位是否为0,为0表示发送缓冲寄存器不为空,即有数据,表示发送正忙,咱还不能写数据到此寄存器需等待。
/*检查是否收到数据,参考S3C6410手册P1096*/
#define RC_BUSY while(!(UTRSTAT0 & 1)) //检测UTRSTAT0的第一位是否为0,为0表示接收缓冲寄存器为空,即没有有效数据,此时不能读该寄存器获得接收数据,需等待。
void uart_init(void)
{
/*设置GPA0-1为UART_com0功能,参考S3C6410手册P312*/
GPACON &= ~(0xff);
GPACON |= 0x22;
/*设置8N1,参考S3C6410手册P1091*/
ULCON0 = 3; //这里设置UART行控制器,行控制器用来选择操作模式,设定奇偶校验,设置每帧中停止位个数,数据位的个数等。
//具体设置请看6410数据手册UART章节,这里赋值为3,即设置为:普通操作模式,无校验,每帧一位停止位,数据位个数为8位(就由1-0位控制)
/*设置采用轮询模式,参考S3C6410手册P1092*/
UCON0 |= (1 << 2) | (1 << 0); //这里就是设置第2位,第0位,这两位的设置是设置成轮询模式,其他位默认0,具体请看其他位的设置对应什么。
//位11-10=00,表示使用PCLK作为UART波特率时钟源,位9=0,设置中断请求类型为脉冲,位8=0,设置接收中断请求类型为脉冲,
//其他的请具体看手册吧
/*把FIFO关掉*/
UFCON0 = 0;
UMCON0 = 0;
/*配置波特率为115200,参考S3C6410手册P1101*/
UBRDIV0 = 34;//34.8<--115200
UDIVSLOT0 = 0xdfdd;//13<--0.8 //这里得到用16*0.8=12.8,四舍五入得到13,然后查看手册UART章节表UDIVSLOTn,找到对应13的值0xdfdd
}
波特率的设置过程:
#include "regs.h"
#include <stdarg.h>
/*va_list
*va_start
*va_end
*va_arg
*/
/*检查上次数据是否发完,参考S3C6410手册P1096*/
#define TR_BUSY while(!(UTRSTAT0 & 2)) //检测UTRSTAT0的第二位是否为0,为0表示发送缓冲寄存器不为空,即有数据,表示发送正忙,咱还不能写数据到此寄存器需等待。
/*检查是否收到数据,参考S3C6410手册P1096*/
#define RC_BUSY while(!(UTRSTAT0 & 1)) //检测UTRSTAT0的第一位是否为0,为0表示接收缓冲寄存器为空,即没有有效数据,此时不能读该寄存器获得接收数据,需等待。
void uart_init(void)
{
/*设置GPA0-1为UART_com0功能,参考S3C6410手册P312*/
GPACON &= ~(0xff);
GPACON |= 0x22;
/*设置8N1,参考S3C6410手册P1091*/
ULCON0 = 3; //这里设置UART行控制器,行控制器用来选择操作模式,设定奇偶校验,设置每帧中停止位个数,数据位的个数等。
//具体设置请看6410数据手册UART章节,这里赋值为3,即设置为:普通操作模式,无校验,每帧一位停止位,数据位个数为8位(就由1-0位控制)
/*设置采用轮询模式,参考S3C6410手册P1092*/
UCON0 |= (1 << 2) | (1 << 0); //这里就是设置第2位,第0位,这两位的设置是设置成轮询模式,其他位默认0,具体请看其他位的设置对应什么。
//位11-10=00,表示使用PCLK作为UART波特率时钟源,位9=0,设置中断请求类型为脉冲,位8=0,设置接收中断请求类型为脉冲,
//其他的请具体看手册吧
/*把FIFO关掉*/
UFCON0 = 0;
UMCON0 = 0;
/*配置波特率为115200,参考S3C6410手册P1101*/
UBRDIV0 = 34;//34.8<--115200
UDIVSLOT0 = 0xdfdd;//13<--0.8 //这里得到用16*0.8=12.8,四舍五入得到13,然后查看手册UART章节表UDIVSLOTn,找到对应13的值0xdfdd
}
波特率的设置过程:
UBRDIV0中的值决定串行Rx/Tx时钟波特率,具体计算如下图:
(可怜啊,这有是两幅截图呢,关于波特率的计算,来自于6410datasheetUART章节,请主动查看)
void uputchar(char c)
{
TR_BUSY;
/*把要发送的数据写到发送寄存器,参考S3C6410手册P1100*/
UTXH0 = c;
}
char ugetchar(void)
{
RC_BUSY;
/*硬件会把收到的数据自动放到URXH0里,参考S3C6410手册P1100*/
return URXH0;
}
void _uputs(char *buf)
{
while(*buf != '\0'){
uputchar(*buf);
if(*buf == '\n'){
uputchar('\r');
}
buf++;
}
}
void uputs(char *buf)
{
_uputs(buf);
uputchar('\n');
uputchar('\r');
}
char *ugets(char *buf)
{
char *save = buf;
char c;
while((c = ugetchar()) != '\r'){
*buf = c;
uputchar(c);
buf++;
}
*buf = '\0';
uputchar('\r');
uputchar('\n');
return save;
}
void itoa(unsigned int d, char *buf)
{
int i;
if(d < 10){
buf[0] = d + '0';
buf[1] = '\0';
return;
}
itoa(d / 10, buf);
for(i = 0; buf[i] != '\0'; i++){
;
}
buf[i] = (d % 10) + '0';
buf[i + 1] = '\0';
}
void xtoa(unsigned int d, char *buf)
{
int i;
if(d < 16){
if(d < 10){
buf[0] = d + '0';
buf[1] = '\0';
}else{
buf[0] = d - 10 + 'a';
buf[1] = '\0';
}
return;
}
xtoa(d / 16, buf);
for(i = 0; buf[i] != '\0'; i++){
;
}
if((d % 16) < 10){
buf[i] = (d % 16) + '0';
buf[i + 1] = '\0';
}else{
buf[i] = (d % 16) - 10 + 'a';
buf[i + 1] = '\0';
}
}
/*%s %c %d %x*/
//uprintf("hello %d %c %x %s\n", 10, 'a', 0x100, "d");
//va_start 建立对应关系
//va_end 取消对应关系
//va_list 对应关系变量类型
//va_arg 根据对应关系取出相应的数据
int uprintf(const char *fmt, ...)
{
va_list ap;
char c;
int d;
char *s;
char buf[64];
va_start(ap, fmt);
while(*fmt != '\0'){
if(*fmt == '%'){
fmt++;
switch(*fmt){
case 'c':
c = va_arg(ap, int);
uputchar(c);
break;
case 'd':
d = va_arg(ap, int);
if(d < 0){
uputchar('-');
d = -d;
}
itoa(d, buf);
_uputs(buf);
break;
case 's':
s = va_arg(ap, char *);
_uputs(s);
break;
case 'x':
d = va_arg(ap, int);
xtoa(d, buf);
_uputs(buf);
break;
case '%':
break;
default:
break;
}
}else{
uputchar(*fmt);
if(*fmt == '\n'){
uputchar('\r');
}
}
fmt++;
}
va_end(ap);
}
main.c:
#include "common.h"#include "regs.h"int main(int argc, char **argv){char c;char buf[1024];uart_init();c = ugetchar();uputchar(c);uputs("hello uputs...");ugets(buf);uputs(buf);uprintf("hello uprintf()\n");uprintf("hello %c %s\n", 'x', "ssssssssss");uprintf("abcd%d %c %s %x\n", 100, 'b', "hello uprintf", 0x100);return 0;}
说明:
串口绝对是个重要的东西,本站只是分析了串口初始化的过程,其实串口的还有一些地方没有讲到,那就在需要的时候多方资料学习。
关于本站的任何疑问,请来群交流,ES6 :180631429
入群请务必附加入群请求说明,因为防止广告号入群打广告,给志同道合的群友造成不必要的麻烦,影响我们的心情。
附加信息请包含以下关键字:学习,嵌入式,交流,ES,空间,CSDN,疯子,壳,蓝天,飞雪,骑士……
愿我们一起,共同进步。
- 第五站,我想对社会说——uart串口程序分析
- 我想对师弟师妹说——外企hr
- 我想对你说
- 同人女,我想对你说——黄金圣斗士对同人女的真情告白
- 儿子,我想对你说
- 粗心,我想对你说
- 朋友,我想对你说
- 潘,我想对你说。。。
- 2017我想对你说
- 2017我想对自己说
- [软件人生]关于离婚对孩子的影响——我想说,我经历
- 其实我想说——胡言乱语
- UART串口处理经典程序
- 示波器分析UART串口数据
- 示波器分析UART串口数据
- 串口——RS232与UART
- 三 ARM9(S3C2440)的串口UART——程序实例讲解
- [思语]_心上人,我想对你说
- Windows Store apps开发[44]AppBar总结
- 第三站,我们才是统治者——KEY按键
- 语音信号的短时自相关序列求解以及xcorr与autocorr问题
- 第四站,把握生命的节奏——CLK初始化
- Adobe Reader卸载或升级后,删除Adobe Reader的Cmap文件夹及文件
- 第五站,我想对社会说——uart串口程序分析
- 闲聊linux中的input设备(5) 她那含情脉脉的眼神
- 第六站,来到大都市——nandflash程序完全解析
- struts第十三天--输出带占位符的资源信息
- win7建立无线wifi热点的几个常见的问题
- libvirt(virsh命令介绍)
- 自己动手写操作系统
- 不伤眼睛的文字背景色
- reids +hiredis 安装详解