九.ARM裸机学习之串口通信详解2(S5PV210串行通信编程详解)

it2022-07-02  189

版权声明:本文为博主原创文章,允许转载请注明。谢谢! <a class="copy-right-url" href=" https://blog.csdn.net/wangweijundeqq/article/details/78534300"> https://blog.csdn.net/wangweijundeqq/article/details/78534300</a> </div> <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css"> <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css"> <div class="htmledit_views" id="content_views"> 1、整个程序流程分析 (1)整个串口通信相关程序包含2部分:uart_init负责初始化串口,uart_putc负责发送一个字节,uart_gec负责接收一个字节。 2、串口控制器初始化关键步骤 (1)初始化串口的Tx和Rx引脚所对应的GPIO(查原理图可知Rx和Rx分别对应GPA0_1和GPA0_0) (2)GPA0CON(0xE0200000),bit[3:0] = 0b0010 bit[7:4] = 0b0010 (3)初始化这几个关键寄存器UCON0 ULCON0 UMCON0 UFCON0 UBRDIV0 UDIVSLOT0 3、主要的几个寄存器 (1)ULCON0 = 0x3 // 0校验位、8数据位、1停止位 (2)UCON = 0x5 // 发送和接收都是polling mode (3)UMCON0 = 0x0 // 禁止modem、afc (4)UFCON0 = 0x0 // 禁止FIFO模式 (5)UBRDIV0和UDIVSLOT0和波特率有关,要根据公式去算的 4、在C源文件中定义访问寄存器的宏 定义好了访问寄存器的宏之后,将来写代码时直接使用即可。 5、串口Tx、Rx对应的GPIO的初始化 给GPA0CON的相应bit位赋值为相应值,用C语言位操作来完成。 6、UCON、ULCON、UMCON、UFCON等主要控制寄存器 依据上节中分析的值进行依次设置即可。 7、波特率的计算和设置 (1)第一步,用PCLK_PSYS和目标波特率去计算DIV_VAL: DIV_VAL = (PCLK / (bps x 16))-1 (2)第二步,UBRDIV0寄存器中写入DIV_VAL的整数部分 (3)第三步,用小数部分*16得到1个个数,查表得uBDIVSLOT0寄存器的设置值 1.7.8.4、串口发送和接收函数的编写 (1)写发送函数,主要发送前要用while循环等待发送缓冲区为空才能发送。 发送接收状态寄存器:UTRSTAT0 uart.c: /* 包含串口初始化程序,串口发送程序,串口接收程序 */ #define GPA0CON 0xE0200000 #define UCON0 0xE2900004 #define ULCON0 0xE2900000 #define UMCON0 0xE290000C #define UFCON0 0xE2900008 #define UBRDIV0 0xE2900028 #define UDIVSLOT0 0xE290002C #define UTRSTAT0 0xE2900010 #define UTXH0 0xE2900020 #define URXH0 0xE2900024 #define rGPA0CON (*(volatile unsigned int *)GPA0CON) #define rUCON0 (*(volatile unsigned int *)UCON0) #define rULCON0 (*(volatile unsigned int *)ULCON0) #define rUMCON0 (*(volatile unsigned int *)UMCON0) #define rUFCON0 (*(volatile unsigned int *)UFCON0) #define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0) #define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0) #define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0) #define rUTXH0 (*(volatile unsigned int *)UTXH0) #define rURXH0 (*(volatile unsigned int *)URXH0) //串口初始化程序 void uart_init(void) { // 初始化Tx Rx对应的GPIO引脚 rGPA0CON &=~( 0xff<< 1); //把寄存器的bit0~7全部清零 rGPA0CON |= 0x00000022; // 0b0010, Rx Tx //几个主要的寄存器 rULCON0 = 0x3; // 0校验位、8数据位、1停止位 rUCON0 = 0x5; // 发送和接收都是polling mode rUMCON0 = 0; // 禁止modem、afc rUFCON0 = 0; // 禁止FIFO模式 // 波特率设置 DIV_VAL = (PCLK / (bps x 16))-1 // PCLK_PSYS用66MHz算 余数0.8 //rUBRDIV0 = 34; //rUDIVSLOT0 = 0xdfdd; // PCLK_PSYS用66.7MHz算 余数0.18 // DIV_VAL = (66700000/(115200*16)-1) = 35.18 rUBRDIV0 = 35; // (rUDIVSLOT中的1的个数)/16=上一步计算的余数=0.18 // (rUDIVSLOT中的1的个数 = 16*0.18= 2.88 = 3 rUDIVSLOT0 = 0x0888; // 3个1,查官方推荐表得到这个数字 } //串口发送程序,发送一个字节 void uart_putc(char c) { // 串口发送一个字符,其实就是把一个字节丢到发送缓冲区中去 // 因为串口控制器发送1个字节的速度远远低于CPU的速度,所以CPU发送1个字节前必须 // 确认串口控制器当前缓冲区是空的(意思就是串口已经发完了上一个字节) // 如果缓冲区非空则位为0,此时应该循环,直到位为1 while (!(rUTRSTAT0 & ( 1<< 1))); rUTXH0=c; } //串口接收程序,发送一个字节 char uart_getc(void) { while (!(rUTRSTAT0 & ( 1<< 0))); return (rURXH0 & 0x0f); } Makefile: uart. bin: start.o led.o clock.o uart.o main.o arm-linux-ld -Ttext 0x0 -o uart.elf $^ arm-linux-objcopy -O binary uart.elf uart.bin arm-linux-objdump -D uart.elf > uart_elf.dis gcc mkv210_image.c -o mkx21 0 ./mkx21 0 uart.bin 210.bin %.o : %.S arm-linux-gcc -o $@ $< -c -nostdlib %.o : %.c arm-linux-gcc -o $@ $< -c -nostdlib clean: rm *.o *.elf *.bin *.dis mkx21 0 -f

最新回复(0)