UART串口编程
来源:互联网 发布:seo整站优化多少费用 编辑:程序博客网 时间:2024/06/17 01:05
基础知识:
1.波特率:每秒传输的二进制位数,bps。
2.UART用的是标准TTL/CMOS逻辑电平,可以通过MAX3232转换成RS-232逻辑电平。RxD/TxD数据线以位为最小数据传输单位。
3.帧:有效传输单位,具有完整数据意义。里面包含:起始位,数据位,校验位,停止位。一帧数据可以有5-8个数据位,从最低位开始传输,传输前约定好传输的格式和波特率。所以能达到发送和接受的数据同步。
4.奇偶校验:所有数据位中包含1的个数。
5.帧格式:n个停止位+起始位+(低)数据位(高)+奇偶校验位+n个停止位。。。帧的分割是有起始位来标志的。
6.UART工作流程:
发送数据:CPU----》FIFO-------》发送移位寄存器---------》TxD数据线
CPU将数据通过总线发送到FIFO中,UART将FIFO中的数据复制到发送移位寄存器中。发送移位寄存器根据传输格式(添加开始位,数据位,校验位,中止位)一位一位的发送到TxD数据线上发射。
接受数据:RxD数据线--------》接受移位寄存器-----》FIFO----------》CPU
接受移位把RxD数据线上的数据一位一位接受过来,然后复制到FIFO中,CPU就可以访问到FIFO中数据了。
7.硬件控制流:这个可以联系到TCP三次握手,当要发送数据时,要等待接受方准备好,并返回个准备好的信号。当发送方接受到这个信号,才开始发送数据。
只有当nCTS接受到信号后TxD才会发送数据。
8.设置波特率除数因子UBRDIV0。公式:UBRDIVn = (int)((Uart Clock)/(baud)/16) -1; Uart Clock:UART时钟频率。 baud:波特率。一般程序中公式将演变成:rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );./ 为点除,因为pclk/16后为整数,所以点除得到float。+0.5 则是为强转时能够取到整数,因为c语言中强转是直接舍弃小数部分,而该公式要求四舍五入。
如:baud为115200bps 且UART时钟频率为40MHz。
UBRDIVn = (int)(pclk/16./baud+0.5) -1
= (int)22.2-1
= 21
9.UART线性控制寄存器:设置传输格式,即是帧格式 10.设置UCON寄存器,设置数据访问的方式:中断,轮询,DMA。以及时钟分频,为波特率选择时钟频率。
11.是否使用FIFO控制寄存器,这里使用了非FIFO模式,就不贴寄存器设置图片了。
12.UTRSTAT0寄存器,相当于一个状态寄存器,实时监控UART是否有数据发来或者数据是否发送完毕。
13.UTXH0发送数据寄存器,URXH0接受数据寄存器。
14.还要设置下IO端口,以及上拉电阻之类的。
代码部分:
#include<stdio.h> #include<stdarg.h> #define rULCON0 (*(volatile unsigned int*)0x50000000) //uart 0设置传输格式 #define rUCON0 (*(volatile unsigned int*)0x50000004) //设置时钟源,访问方式 #define rUFCON0 (*(volatile unsigned int*)0x50000008) //FIFO寄存器 #define rUMCON0 (*(volatile unsigned int*)0x5000000c) //硬件控制流 #define rUTRSTAT0 (*(volatile unsigned int*)0x50000010) //检测是否发生/接受完毕 #define rUERSTAT0 (*(volatile unsigned int*)0x50000014) //错误状态寄存器 #define rUFSTAT0 (*(volatile unsigned int*)0x50000018) //FIFO状态寄存器 #define rUFASTAT0 (*(volatile unsigned int*)0x5000001c) //Modem状态寄存器 #define rUTXH0 (*(volatile unsigned int*)0x50000020) //发生缓存寄存器 #define rURXH0 (*(volatile unsigned int*)0x50000024) //接受缓存寄存器 #define rUBRDIV0 (*(volatile unsigned int*)0x50000028)//UART 0 Baud rate divisor #define rGPHCON (*(volatile unsigned int*)0x56000070) //RxD/TxD控制 #define rGPHDAT (*(volatile unsigned int*)0x56000074) //RxD数据控制 #define rGPHUP (*(volatile unsigned int*)0x56000078) //RxD上拉电阻 //#define rUTXH0 (*(volatile unsigned char *)0x50000020)//UART 0 Transmission Hold //#define rURXH0 (*(volatile unsigned char *)0x50000024)//UART 0 Receive buffer #define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch) #define RdURXH0() (*(volatile unsigned char *)0x50000024) #definte uint32 unsigned int #define uint8 unsigned char //定义串口传输格式 typedef struct UartMode{ uint8 dateLen;//date length 5/6/7/8 uint8 stopLen;//stop bite 1/2 uint8 parity; //parity 0==no parity 1==odd parity 2==even parity }UartMode; static uint32 UartNum = 0; //做下前置声明 void Uart_Port_Init(int UartNum); int Uart_init(UartMode mode,uint32 baud,uint32 pclk,uint32 UartNum); char Uart_ReceviceCh(void); void Uart_ReceviceString(char *string); void Uart_SendCh(char ch); void Uart_SendString1(char * string); //延迟程序 void Delay(uint32 time) { uint32 i = 0; if (0==time) time = 400; for(;time > 0;time--){ for(;i < 3000;i++) ; } } //串口端口初始化 void Uart_Port_Init(int UartNum) { rGPHCON = rGPHCON & (~(0xffff)); //置零 if (0 == UartNum) { rGPHCON = rGPHCON | (10 << 4); //设置为RxD[0] TxD[0] }else if(1 == UartNum) { rGPHCON = rGPHCON | (10 << 8); //设置为RxD[1] TxD[1] } else rGPHCON = rGPHCON | (10 << 12); //设置为RxD[2] TxD[2] rGPHUP = 0x0; //不用上拉电阻 } //串口初始化,传输格式,波特率,硬件控制流等 int Uart_Init(UartMode mode,uint32 baud,uint32 pclk,uint32 UartNum) { uint32 allMode; //先把所有模式设置好,然后一次性写入寄存器 //首先判断设置的传输的格式是否正确 if ((mode.dateLen < 5)||(mode.dateLen > 8)){ return 0; } if ((mode.stopLen < 1) || (mode.stopLen > 2)){ return 0; } if ((mode.parity < 0) || (mode.parity > 2)){ return 0; } //判断波特率是否正确 if ((0 == baud) || (baud >115200)){ return 0; } //下面是正式初始化串口了,这里假设是串口0,不再判断了 //设置工作模式和传输格式 allMode = 0; //设置正常模式,红外线接收设置1 //设置奇偶校验 if (0 != mode.parity) { mode.parity = mode.parity + 3; allMode = ((allMode | mode.parity) << 2); } //设置停止位 mode.stopLen = mode.stopLen - 1; allMode = ((allMode | mode.stopLen) << 1); //设置数据位 mode.dateLen = mode.dateLen - 5; allMode = allMode | mode.dateLen; rULCON0 = allMode; //设置串口波特率,即是设置波特率除数因子寄存器 rUBRDIV0 = ((int)(pclk/16./baud+0.5)-1); rUFCON0 = 0x0 ;//非FIFO rUMCON0 = 0x0 ;//非硬件控制流模式 rUCON0 = 0x805;//使用中断或者轮询模式访问数据 Delay(5); } //接收一个字符 char Uart_ReceviceCh(void) { //不判断串口号UartNum while(!(rUTRSTAT0 & 0x1));//循环查看数据是否到来,这里有阻塞,可以用if判断 return RdURXH0(); } //接收字符串 void Uart_ReceviceString(char *string) { //如果这里不进行串口初始化,那在主函数调用本函数前就要初始化 char *string2 = string; char ch; //以换行字符为标志,只接受一行字符串 while((ch = ReceviceCH())!= '\r') { //退格符 if (ch == '\b'){ //先判断下是否是首字母退格,把地址转换为int型才能比较大小 //如果相等,则不能退格 if ((int)string2 < (int)string) { Uart_printf("\b \b"); string--;//后退一个字符 } }else{ *string++ = ch; Uart_SendCh(ch); } } *string = '\0';//字符串接受标志 Uart_SendCh('\n');//接受完毕,补充一个回车键 } //发送字符 void Uart_SendCh(char ch) { //不判断串口号,直接默认为串口0 //如果是换行符,发送一个回车键 if (ch == '\n') { while(!(rUTRSTAT0 & 0x2));//循环等待发送缓存为空 WrUTXH0('\r');//发送回车符 } while(!(rUTRSTAT0 & 0x2)); Delay(10); WrUTXH0(ch);//发送字符 } //接收字符串 void Uart_SendString(char * string) { while(*string) Uart_SendCh(*string++); } //格式化打印 void Uart_Printf(char *fmt,...) { va_list ap;//可变参数列表 char string[256]; va_start(ap,fmt); vsprintf(string,fmt,ap); Uart_SendString(string); va_end(ap); }
0 0
- linux uart串口编程
- UART串口编程
- 异步串口uart的c语言编程
- ARM:UART串口异步通信驱动编程
- UART串口
- 串口uart
- 串口UART
- 串口UART
- UART(异步串口通信)裸板编程
- Uart串口实验--TQ2440
- linux UART串口驱动
- S3C2440 UART串口驱动
- S3C2440 UART串口驱动
- UART串口通信
- CC2430 串口通信UART
- Uart串口实验问题
- S3C2440 UART串口驱动
- S3C2440 UART串口驱动
- Aspose.Pdf for .NET控件PDF文档到Excel、EPS、SVG等的转换
- POJ 1233 并查集,最小生成树
- c++继承 虚函数 内存分配
- HDU 2594 Simpsons’ Hidden Talents (KMP)
- struct 小结
- UART串口编程
- hibernate 连接 oracle出错
- 网上关于sort结构体排序都不完整,我来写一个完整版的
- 利用JAVA Comparator接口实现数组排序
- 线程的join()方法 模拟做饭场景
- GUI用户界面编程
- bash-completion
- TOJ 2034. Just the Facts
- 命令行模式下java命令找不到主类