11_UART
文章目录
串口打印调试信息,外界各种设备
1、串口连接芯片图
2、串口传输一个字节的过程
传输数据时的逻辑电平如下两图:
3、发送接收过程
波特率:115200,8n1
每一位:t = 1/115200
传输1Byte:需要10位(start, Data, Stop)
t = 10 / 115200
1秒能传输:1/t = 115200/10 = 11520 byte
4、编写UART函数
4.1、初始化函数uart0_init()
编写初始化函数:void uart0_init()
4.1.1、设置引脚用于串口
//GPH2,3用于TxD0,RxD0
GPHCON &= ~((3<<4) | (3<<6));
GPHCON |= ((2<<4) | (2<<6));
4.1.2、使能上拉
//使能内部上拉使得引脚在平时为高电平
GPHUP &= ~((1<<2) | (1<<3));
4.1.3、设置波特率
设置UCON0寄存器
UBRDIV0 = (int)( UART clock / ( buad rate x 16) ) –1
UART clock = PCLK = 50MHz
UBRDIV0 = (int)( 50000000 / ( 115200 x 16) ) –1 = 26
UCON0 = 0x00000005;
/* PCLK,中断/查询模式
* UCON0[11:10] = 00(0x00000005),10(0x00000805) :选为PCLK
* UOCN0[3:2] = 01,Interrupt request or polling mode
* UOCN0[1:0] = 01,Interrupt request or polling mode
*/
4.1.4、设置数据格式
ULCON0 = 0x00000003;
/* 8n1: 8个数据位,无校验位,一个停止位
* ULCON0[5:4:3] = 0xx :No parity(无校验位)
* ULCON0[2] = 0 :One stop bit per frame(一个停止位)
* ULCON0[1:0] = 11 :8-bits(8个数据位)
*/
4.2、int putchar(int c)函数
4.2.1、判断状态
while (!(UTRSTAT0 & (1<<2)));
此位为0表明上一次的数据还没发送出去,等待。
4.2.2、发送数据
UTXH0 = (unsigned char)c;
寄存器UTXH0定义为unsigned char类型。
4.3、int getchar(void)函数
4.3.1、判断状态
while (!(UTRSTAT0 & (1<<0)));
此位为0表明上一次的数据还没接收,等待。
4.3.2、返回接收到的数据
return URXH0;
4.4、int puts(const char *s)函数
输出字符串函数:
while(*s)
{
putchar(*s);
s++;
}
5、UART头文件
//uart.h
#ifndef _UART_H
#define _UART_H
void uart0_init();
int putchar(int c);
int getchar(void);
int puts(const char *s);
#endif
6、main函数
#include "s3c2440_soc.h"
#include "uart.h"
int main(void)
{
unsigned char c;
uart0_init();
puts("Hello,world!\n\r");
while(1) {
c = getchar();
if (c == '\r') {
putchar('\n');
}
if (c == '\n') {
putchar('\r');
}
putchar(c); /* 若无这个则串口不显示输入的字符,即没有回显 */
}
return 0;
}
7、编写自己的printf测试函数
Printf中的格式字符:
my_printf测试函数:
#include <stdio.h>
//#include <stdarg.h>
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
//#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
//#define va_arg(ap,t) (ap = ap +_INTSIZEOF(t), *(t *)(ap -_INTSIZEOF(t)))
#define va_arg(ap,t) (*(t *)(ap = ap +_INTSIZEOF(t),ap -_INTSIZEOF(t)))
#define va_end(ap) ( ap = (va_list)0 )
struct person{
char *name;
int age;
char score;
int id;
};
/* 由于在x86(32位机器)平台下,GCC编译器默认按4字节对齐 */
/*int printf(ocnst char *formt, ...);
*依据: x86平台,函数调用参数是使用堆栈来实现的
*目的: 将所有传入的参数全部打印出来
*/
int push_test(const char *format, ...)
{
//char *p = (char *)&format;
int i;
struct person per;
char c;
double d;//float d;
va_list p;
//1==========================
/* 指针对连续空间操作时: 1)取值 2)移动指针 */
printf("arg1: %s\n",format);
//2==========================
//p = p +sizeof(char *);
va_start(p, format);
/* 指针对连续空间操作时: 1)取值 2)移动指针 */
//i = *((int *)p);
//p = p + sizeof(int);
i = va_arg(p, int);
printf("arg2: %d\n",i);
//3==========================
/* 指针对连续空间操作时: 1)取值 2)移动指针 */
//per = *((struct person *)p);
//p = p + sizeof(struct person);
per = va_arg(p, struct person);
printf("arg3: .name = %s, .age = %d, .score= %c, .id=%d\n",\
per.name, per.age, per.score, per.id);
//4==========================
/* 指针对连续空间操作时: 1)取值 2)移动指针 */
//c = *((char *)p);
/* p = p + ((sizeof(char) + 3) & ~3);
* #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
* 当sizeof(n)=1/2/4时,_INTSIZEOF(n)都等于4
*/
c = va_arg(p, int); /*c = va_arg(p, char);
由于传递参数时保持字符对齐,
需要把char类型转换成int类型*/
printf("arg4: %c\n",c);
//5==========================
/* 指针对连续空间操作时: 1)取值 2)移动指针 */
//d = *((double *)p); /* 默认按照doubled = *((float *)p); */
//p = p + sizeof(double);
d = va_arg(p, double);
/* 避免"野指针"出现 */
//p = (char *)0;
va_end( p );
printf("arg5: %f\n",d);
return 0;
}
int main(int argc,char **argv)
{
struct person per={"Zhang Dengyu",23,'A',191040043};
printf("sizeof(char )=%d\n",sizeof(char ));
printf("sizeof(int )=%d\n",sizeof(int ));
printf("sizeof(char *)=%d\n",sizeof(char *));
printf("sizeof(char **)=%d\n",sizeof(char **));
printf("sizeof(struct person)=%d\n",sizeof(struct person));
//push_test("HDU_DZ_ZDY");
//push_test("HDU_DZ_ZDY",8023);
//push_test("HDU_DZ_ZDY",8023,per);
//push_test("HDU_DZ_ZDY",8023,per,'c');
push_test("HDU_DZ_ZDY",8023,per,'c',3.14);
return 0;
}
代码解析: