TQQ2440第三节:串口
做嵌入式的基本上都清楚,板子基本上跑起来了,第一个肯定要配置的是串口,便于我们后面调试信息的输出,和一些系统参数的输出,让我们有更直观看见程序的运行。
—————————————————————————————————————————————
硬件平台:TQ2440 (S3C2440A)
开发环境:ADS1.2
时 间:2010-12-12
—————————————————————————————————————————————
1:硬件电路:
底板电路 核心板上的连接管脚
由于TQ2440的板子上只引出了一个串口,也就是用的UART0作为COM1,所以我吗只需要配置相关的引脚为串口功能即可。
接着参考2440的说明文档:
所以把GPH相关的GPH0-3都配置为第二功能UART功能。即可以上至完成了管脚的配置,接着对UART的功能进行配置。
A:UART寄存器:
从2440的数据手册上我们可以知道他的寄存器的地址都是连接着的,所以我们直接用结构体来表示,因为他有3个串口,所以,我们这里就可以用3个不同的结构体指针来操作不同的寄存器。代码如下:
1: #define IO_CON_BASE 0x560000002: #define IO_DAT_BASE 0x560000043:4: #define UART0_BASE 0x50000000 // UART0 Base Address5: #define UART1_BASE 0x50004000 // UART1 Base Address6: #define UART2_BASE 0x50008000 // UART2 Base Address7:8: #define REG8(x) (*((volatile unsigned char *)(x)))9: #define REG16(x) (*((volatile unsigned short *)(x)))10: #define REG32(x) (*((volatile unsigned long *)(x)))11:12: typedef volatile unsigned char reg8;13: typedef volatile unsigned short reg16;14: typedef volatile unsigned long reg32;15:16: /*17: GPIO_CFG_SET说明: group--表示是那组IO(注意没有GPA)18: index--表示这组中的那个引脚19: type --表示是配置为输入还是输出等其他功能20: */21: #define GPIO_CFG_SET(group,index,type) do{\22: (*(volatile unsigned int*)(IO_CON_BASE+group*0x10))&=~(0x3<<index<<1);\23: (*(volatile unsigned int*)(IO_CON_BASE+group*0x10))|=(type<<index<<1);\24: }while(0)25:26: /*27: GPIO_DAT_SET说明: group--表示是那组IO(注意没有GPA)28: index--表示这组中的那个引脚29: val --表示对此引脚写入的数据30: */31: #define GPIO_DAT_SET(group,index,val) do{\32: (*(volatile unsigned int*)(IO_DAT_BASE+group*0x10))&=~(0x1<<index);\33: (*(volatile unsigned int*)(IO_DAT_BASE+group*0x10))|=(val<<index);\34: }while(0)35: /*36: 因为GPA的控制寄存器,每个引脚只只占用一位,所以为了能统一这里,就没有把37: GPA加进来,而后面的GPB-GPJ的控制寄存器每个引脚对应2位38: */39: enum{GPB=1,GPC,GPD,GPE,GPF,GPG,GPH,GPI,GPJ};40: /*41: 从GPB开始由于用两位表示此引脚的功能所以有四种可能42: 0代表INPUT,1代表OUTPUT,2代表第三功能,3代表第四功能43: */44: enum{INPUT=0,OUTPUT,THI_FUNC,FOR_FUNC};45: /*46: 定义高低电平47: */48: enum{LOW=0,HIG};49:50: // UART Registers51: typedef struct {52: reg32 ULCON; // UART Line Control 由于控制数据格式,常用的为N-8-1模式53: reg32 UCON; // UART Control 控制UART的工作状态,例如DMA,中断等54: reg32 UFCON; // UART FIFO Control 控制UART的FIFO,这里没有用到55: reg32 UMCON; // UART MODEM Control 在MODEM模式下的控制寄存器,这里没有用到56: reg32 UTRSTAT; // UART Tx/Rx Status UART发送和接受状态寄存器57: reg32 UERSTAT; // UART Error Status UART错误状态寄存器58: reg32 UFSTAT; // UART FIFO Status UART---FIFO状态寄存器59: reg32 UMSTAT; // UART MODEM Status UART---MODEM状态寄存器60: reg8 UTXH; // UART Tx Hold UART发送数据寄存器 ##注意这里是一个char类型的61: reg8 pad0[3];62: reg8 URXH; // UART RX Buffer UART接受数据寄存器 ##注意这里是一个char类型的63: reg8 pad1[3];64: reg32 UBRDIV; // UART Baud Rate Divisor UART的波特率产生器的分频率65: } regUART;66:67: #define pUART0 ((regUART *)UART0_BASE)68: #define pUART1 ((regUART *)UART1_BASE)69: #define pUART2 ((regUART *)UART2_BASE)
2:2440的UART的配置
上面已经把相关的寄存器介绍的很清楚了,所以这里的配置就直接给出代码了,因为可以直接参考数据手册得到:
1: void uart_init(void)
2: {
3: //设置GPH[0..3]为uart0的输出引脚
4: GPIO_CFG_SET(GPH,0,THI_FUNC);
5: GPIO_CFG_SET(GPH,1,THI_FUNC);
6: GPIO_CFG_SET(GPH,2,THI_FUNC);
7: GPIO_CFG_SET(GPH,3,THI_FUNC);
8:
9: pUART0->ULCON= 0x03; //N-8-1
10: pUART0->UCON= 0x245; //中断和查询模式
11: pUART0->UFCON= 0x0; //No Use
12: pUART0->UMCON= 0x0; //No Use
13: pUART0->UBRDIV= 26; //当前板子的速度是FCLK:400M,HCLK=100M,PCLK=50M,UATR=115200
14: }
这样串口就能工作起来的了,自己在把链接串口工具配置成相同的波特率就能正常工作了。
3: 相关代码的实现
接下来就是串口发送和接受数据的一些功能函数的实现了,下面也只实现了一些简单的函数:
输出部分:
1: void u_printf(char *fmt,...) //格式化输出
2: {
3: va_list ap;
4: char str[100];
5: va_start(ap,fmt);
6: vsprintf(str,fmt,ap);
7: send_str(str);
8: va_end(ap);
9: }
10: void send_str(char *p_str) //发送一个字符串
11: {
12: while(*p_str!='\0')
13: {
14: if(*p_str=='\n')
15: {
16: send_char('\r');
17: }
18:
19: send_char(*p_str);
20: p_str++;
21: }
22: }
23: void send_char(char cc) //发送一个字符
24: {
25: while(!(pUART0->UTRSTAT& 0x2));
26: pUART0->UTXH=cc;
27: }
输入部分:
1: char get_char(void) //接受一个字符
2: {
3: char cc;
4: while(!(pUART0->UTRSTAT& 0x1));
5: cc=pUART0->URXH;
6: return cc;
7: }
8:
9: void get_str(char *str) //接受一个字符串
10: {
11: /*
12: str_bak是为了存储str地址的,是为了在没有输入的情况下
13: 输入退格,造成程序的崩溃
14: */
15: char *str_bak=str,cc;
16: do{
17: cc = get_char();
18: if(cc=='\b')
19: {
20: if( (int)str_bak < (int)str)
21: {
22: //u_printf("\b \b");
23: send_char('\b');
24: send_char('\b');
25: str--;
26: }
27: }
28: else
29: {
30: *str++ = cc;
31: send_char(cc);
32: }
33: }
34: while(cc!='\r');
35:
36: *str = '\0';
37: send_char('\n');
38: }
4:彩色输出的实现
在公司的调试东西有时候打印的东西太多了,是在没办法找,所以最后实现了这个彩色打印的方法,便于迅速找到自己想得到的打印消息,从而提高工作效率。其彩色打印的原理为:
以下内容来自网上:
+-----------------------------------------------------------------------------------------------+
在 ANSI 兼容终端(例如 xterm、rxvt、konsole 等)里, 可以用彩色显示文本而不仅仅是黑白。
下面的语句就输出高亮的黑色背景的绿色字。
printf("\033[1;40;32m%s\033[0m", Hello,world!\n);
\033 声明了转义序列的开始,然后是 [ 开始定义颜色。后面的 1 定义了高亮显示字符。然后是背景颜色,这里面是40,表示黑色背景。接着是前景颜色,这里面是32,表示绿色。我们用 \033[0m 关闭转义序列, \033[0m 是终端默认颜色。
通过上面的介绍,就知道了如何输出彩色字符了。
下面是对于彩色字符颜色的一些定义:
前景 背景 颜色
---------------------------------------
30 40 黑色
31 41 紅色
32 42 綠色
33 43 黃色
34 44 藍色
35 45 紫紅色
36 46 青藍色
37 47 白色
代码 意义
-------------------------
0 终端默认设置
1 高亮显示
4 使用下划线
5 闪烁
7 反白显示
8 不可见
通过串口收发或显示字符时,我们使用的通常是字符的ASCII码。对于非控制字符,也即键入命令时我们可能使用到的命令字符,在控制台中我们使用了ASCII码值从0x20~0x7e之间的字符。对于控制字符,在常用字符ASCII码对照表中我们可以找到Enter键、Backspace(退格)键以及ESC键的ASCII码,但是却没有上下左右方向键以及Home、End键对应的ASCII码,通过对键盘输入字符的串口收发测试发现,如果在测试时按下了方向键则串口在每次按键后会连续发送出3字节数据,前两字节所有方向键的数据相同,分别是0x1b,0x5b,第3字节对应不同的按键,上下右左方向键分别对应的值为:0x41、0x42、0x43、0x44,Home和End键对应的值为0x48和0x4b。故要检测键盘是否键入了方向键,需要向串口连续读取三字节的数据,同理,要控制光标向左、向右移动或Home、End也需要连续一次向串口发送3字节数据。
+-----------------------------------------------------------------------------------------------+
所以我们只需要通过串口发送相应的指令就OK了,我为了方便将其封装为宏定义的格式:
1: //######################Add by Dreamxi 彩色打印信息##################start
2: //使用格式
3: //cpfcpf(ALLOW_PUT,RED,("+----------------This is Dreamxi Uart cpf test --------------+"));
4: // | | |-------------------------------------------------------------|
5: // 是否允许打印 | |
6: // | |
7: // 打印颜色 |
8: // 打印内容
9: #define ALLOW_PUT 1
10: /*
11: 前景 背景 颜色
12: ---------------------------------------
13: 30 40 黑色
14: 31 41 紅色
15: 32 42 綠色
16: 33 43 黃色
17: 34 44 藍色
18: 35 45 紫紅色
19: 36 46 青藍色
20: 37 47 白色
21: */
22: /* 红 绿 蓝 白 黄 紫红 青蓝 */
23: enum {RED=0,GRE,BLU,WHI,YEL,ZH,GB};
24:
25: #define cpf(DEBUG_MSG,COR,...) do{\
26: if(DEBUG_MSG==1)\
27: {\
28: if(COR==RED)\
29: {\
30: u_printf("\033[1;31;40m");\
31: u_printf(__VA_ARGS__);\
32: }\
33: else if(COR==GRE)\
34: {\
35: u_printf("\033[1;32;40m");\
36: u_printf(__VA_ARGS__);\
37: }\
38: else if(COR==BLU)\
39: {\
40: u_printf("\033[1;34;40m");\
41: u_printf(__VA_ARGS__);\
42: }\
43: else if(COR==WHI)\
44: {\
45: u_printf("\033[1;37;40m");\
46: u_printf(__VA_ARGS__);\
47: }\
48: else if(COR==YEL)\
49: {\
50: u_printf("\033[1;33;40m");\
51: u_printf(__VA_ARGS__);\
52: }\
53: else if(COR==ZH)\
54: {\
55: u_printf("\033[1;35;40m");\
56: u_printf(__VA_ARGS__);\
57: }\
58: else if(COR==GB)\
59: {\
60: u_printf("\033[1;36;40m");\
61: u_printf(__VA_ARGS__);\
62: }\
63: u_printf("\033[0m\r\n");\
64: }\
65: }while(0)
66: //######################Add by Dreamxi 彩色打印信息##################end
使用方法:
1: cpf(ALLOW_PUT,RED,("+----------------This is Dreamxi Uart cpf test --------------+"));
2: cpf(ALLOW_PUT,GRE,("+----------------This is Dreamxi Uart cpf test --------------+"));
3: cpf(ALLOW_PUT,BLU,("+----------------This is Dreamxi Uart cpf test --------------+"));
4: cpf(ALLOW_PUT,WHI,("+----------------This is Dreamxi Uart cpf test --------------+"));
5: cpf(ALLOW_PUT,YEL,("+----------------This is Dreamxi Uart cpf test --------------+"));
6: cpf(ALLOW_PUT,ZH,("+----------------This is Dreamxi Uart cpf test --------------+"));
7: cpf(ALLOW_PUT,GB,("+----------------This is Dreamxi Uart cpf test --------------+"));
最后实现的效果图:
转载于:https://www.cnblogs.com/Dreamxi/archive/2010/12/12/1903804.html
TQQ2440第三节:串口相关推荐
- TQQ2440第三节:串口 MICRO2440 Fclk:Hclk:Pclk学习
http://www.cnblogs.com/Dreamxi/archive/2010/12/12/1903804.html http://blog.chinaunix.net/space.php?u ...
- 详解 Qt 串口通信程序全程图文 (5)
Qt 串口通信程序全程图文是本文介绍的内容,本节也是最后一节,本节主要讲述的是解决一下重要问题的说明: (下面所说的第一个程序是指第一节中写的那个程序,第二个程序是指第三节更改完后的程序,第三个程序是 ...
- 10-ESP8266 SDK开发基础入门篇--上位机通过串口控制ESP8266灯亮灭
https://www.cnblogs.com/yangfengwu/p/11087618.html 其实这一节就是对上三节的综合测试 https://www.cnblogs.com/yangfeng ...
- 多个线程对串口读取 modbus_HART转Modbus转换器
▼更多精彩推荐,请关注我们▼ 第一节 功能说明 HART转Modbus模块实现将HART信号中的数字信号转换为符合Modbus RTU/ASCII标准的RS485信号和RS232信号,实现仪表的数据读 ...
- WIN32 API串口通信编程
WIN32 API串口通讯实例教程 第一节实现串口通讯的函数及串口编程简介 API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作.常用函数及作用下: 函数 ...
- 【开发教程5】疯壳·ARM功能手机-串口实验教程
ARM功能手机 --疯壳·开发板系列 串口实验教程 图1 第一节串口硬件电路 串口通过USB口及手环下载调试线引出,连接MCU的P12与P13引脚,如下图所示: 图2 第二节 UART寄存器 2.1 ...
- [基于STM32底盘控制与ROS上层导航小车制作] 第五节 实现STM32与ubuntu系统下的ROS串口DMA通信,传输底盘速度等信息
系列文章目录 第一节 stm32电机驱动与编码器读取反馈 第二节 stm32电机pid控制 第三节 stm32线速度标定 第四节 stm32添加mpu6050得到angle角度 第五节 实现STM32 ...
- 昆仑通态屏幕制作(连载3)---基础篇(按钮串口发送)
写在开始 经历了两天的努力,终于对这款嵌入式屏幕有了新的认识.下面做下类比: 单片机或者ARM: (1)main函数开始,进行INIT初始化: (2)while(1)循环: (3)外部或内部中断. 以 ...
- python第三方库之学习pyserial库--串口通信
pyserial串口通信库 1.安装pyserial库 2.填写串口参数的注意事项 3.简单封装一下 4.碰到的bug 1.安装pyserial库 pip install pyserial versi ...
最新文章
- 2018-3-18Zookeep
- mysql中一个表最多能有几个auto_mysql--一个表上可以指定几个auto_increment
- python新闻系统_干货 | Python 实现新闻系统内容的增删改查功能
- pythondocumentation是什么_怎样阅读Python官方文档
- java连接数据库的基本操作
- [转载] Go语言的自重写程序
- java 反射 构造器_Java之类的构造器(反射)
- centos yum源_Linux入门珍藏课件系列第一讲:YUM源(图文)
- 从Chrome源码看JS Array的实现
- 联合查询(多表查询)
- 2017个人年终总结
- 码畜 码奴 码农 IT民工和IT其他工种的划分定义
- 手机扫描二维码登录原理
- [转]全图形PPT设计指南
- vs编写java_vs code编写java
- 视频剪辑,大师珍藏的素材都在这里!
- LCD液晶屏接口和显示器接口介绍
- 台湾清华大学物联网--004 物联网无线传输技术
- 杨校老师课堂之CSDN博客查找博文汇总-目录
- 2023跨年代码(烟花+自定义文字+背景音乐+雪花+倒计时)
热门文章
- python播放url音频_如何从URL播放mp3
- linux 双显示器双鼠标
- 鸿蒙os目前支持了哪些硬件,大佬终于把鸿蒙OS讲明白了,收藏了!
- java 拦截鼠标消息 循环_java – 由子组件拦截的swing鼠标侦听器
- 教师资格证面试计算机教案模板,2017年教师资格证面试教案模板
- python操作目录_Python语言目录操作一
- pako 压缩lottie动效资源方案
- SDN(五) Netgear R6220从刷机到配置 OpenvSwitch交换机
- AndroidVideoCache源码浅析
- 2008精选新年祝福语