Home » 华清嵌入式 » arm 通讯接口

arm 通讯接口

编 辑:Y ┊ 时 间:2022年03月07日 ┊ 访问: 19 次

60271-i5h6752a63.png

29290-8s2b4bmh0de.png

串行通讯

  1. 单线
  2. 双线 uart (全双工 异步)
  3. 双线 i2c (半双工 同步)
  4. 三线 spi (全双宫 同步)

并行通讯

  • 多跟数据线,地址线,如内存

查引脚

34727-h4auzz7m8e.png

我们使用串口II,中间的这个
我们接下来看cpu哪个引脚连着串口II

95226-k84287u0qi.png

92272-8i7jztpjjpk.png

搜索
69493-379lytbwr9l.png

查询cpu的引脚
05721-1c4fsrrfhnb.png

47372-9z6qn9uk6sm.png

这个引脚不一定只能做串口
30564-jd2guxaltgj.png
这个除了输入输出,还能做串口
做串口发送输出

看手册

这颗板子支持4个UART,但是我们只使用了三个

02298-wxq8n9tffp.png

这个引脚叫GPA1_0和GPA1_1
29584-pc378uc56g.png

搜一下GPA1
06622-n88fo04e94i.png

配置寄存器

配置到串口模式

1_1在手册里面是
GPA1CON[1]
86053-b1k58086uuc.png

之前控制灯我们设置为输出模式
现在我们设置为串口模式
0x2 = UART_2_TXD
同理,我们接受也是一样的
52611-ox0q5piqmzk.png

模板

main.c

/*
  功能:   实现通过串口com2 输出字符显示

  1. 看电路图找到CPU对应的控制管脚   GPA1_1  GPA1_0
  2. 看芯片手册,找到对应寄存器
     a. 配置管脚为串口模式
     b. 功能块设置
  3. 编程   

*/

int main(void) 
{

    return 0;
}

Makefile:

all:
    arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o start.o start.S
    arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o main.o main.c
    arm-none-linux-gnueabi-ld start.o main.o -Tmap.lds -o uart.elf
    arm-none-linux-gnueabi-objcopy -O binary  uart.elf uart.bin
    arm-none-linux-gnueabi-objdump -D uart.elf > uart.dis
clean:
    rm -rf *.bak start.o main.o uart.elf uart.bin uart.dis

start.s

    .global  delay1s 
    .text     
    .global _start
_start:
        b        reset                        @0x00
        ldr        pc,_undefined_instruction  @0x04
        ldr        pc,_software_interrupt     
        ldr        pc,_prefetch_abort
        ldr        pc,_data_abort
        ldr        pc,_not_used
        ldr        pc,_irq
        ldr        pc,_fiq

_undefined_instruction: .word  _undefined_instruction
_software_interrupt:    .word  _software_interrupt
_prefetch_abort:        .word  _prefetch_abort
_data_abort:            .word  _data_abort
_not_used:                .word  _not_used
_irq:                    .word  _irq 
_fiq:                    .word  _fiq


reset: 
    ldr    r0,=0x40008000      @设置异常向量表的启始地址为 0x40008000
    mcr    p15,0,r0,c12,c0,0        @ Vector Base Address Register

init_stack:
    ldr        r0,stacktop         /*get stack top pointer*/

    /********svc mode stack********/
        mov        sp,r0
        sub        r0,#128*4          /*512 byte  for irq mode of stack*/
    /****irq mode stack**/
        msr        cpsr,#0xd2
        mov        sp,r0
        sub        r0,#128*4          /*512 byte  for irq mode of stack*/
    /***fiq mode stack***/
        msr     cpsr,#0xd1
        mov        sp,r0
        sub        r0,#0
    /***abort mode stack***/
        msr        cpsr,#0xd7
        mov        sp,r0
        sub        r0,#0
    /***undefine mode stack***/
        msr        cpsr,#0xdb
        mov        sp,r0
        sub        r0,#0
   /*** sys mode and usr mode stack ***/
        msr        cpsr,#0x10
        mov        sp,r0             /*1024 byte  for user mode of stack*/

        b        main

delay1s:
     ldr      r4,=0x1ffffff   
delay1s_loop:
     sub    r4,r4,#1
     cmp   r4,#0         
     bne    delay1s_loop
     mov   pc,lr    


    .align    4

    /****  swi_interrupt handler  ****/


stacktop:    .word         stack+4*512

.data

stack:    
  .space  4*512
.end

map.lds


OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
    . = 0x40008000;  /*指定链接的起始地址   */
    . = ALIGN(4);
    .text      :
    {
        start.o(.text)
        *(.text)
    }
    . = ALIGN(4);
    .data : 
    { *(.data) }
    . = ALIGN(4);
    .bss :
     { *(.bss) }
}

实现

#define GPA1CON (*(volatile unsigned int *)*0x11400020)
void uart_init(void)
{
    //1. 配置pin GPA1_1 和 GPA1_0 为串口模式
    //*0x11400020 = 0x22
    GPA1CON = 0x22;
    
}

设置串口相关功能

01963-ocn3s3vvldl.png

43460-779zczmlwnp.png

59164-4wjkx8pjj4o.png

Transmit Shifter 移位寄存器
Buad-rate Generator 波特率

56213-vzhjpq0pxoh.png

为什么这里有这么多基地址,因我我们有0-3个com口

ULCONn 线控

28.6.1.1 ULCONn (n = 0 to 4)
 Base Address: 0x1380_0000, 0x1381_0000, 0x1382_0000, 0x1383_0000, 0x1384_0000
 Address = Base Address + 0x0000, Reset Value = 0x0000_0000

Word Length 字长

表示每一帧发送的位数
27581-omlkvhjvfk.png
Indicates the number of data bits UART transmits or receives
per frame.
00 = 5 bits
01 = 6 bits
10 = 7 bits
11 = 8 bits

Number of Stop Bit 停止位

Specifies how many stop bits UART uses to signal end-offrame signal.
0 = One stop bit per frame
1 = Two stop bit per frame

Parity Mode 校验位

Specifies the type of parity that UART generates and checks
during UART transmit and receive operation.
0xx = No parity
100 = Odd parity
101 = Even parity
110 = Parity forced/ checked as 1
111 = Parity forced/ checked as 0

UCONn 串口控制寄存器

28.6.1.2 UCONn (n = 0 to 4)
 Base Address: 0x1380_0000, 0x1381_0000, 0x1382_0000, 0x1383_0000, 0x1384_0000
 Address = Base Address + 0x0004, Reset Value = 0x0000_0000

86523-soz8ougqf1.png

90253-pgso66hmwm.png

62450-1254exk1b81.png

Receive Mode 采用什么方式读取

Determines which function is able to Read data from UART
receive buffer.
00 = Disables
01 = Interrupt request or polling mode
10 = DMA mode
11 = Reserved

这里使用 polling mode

Transmit Mode

传输模式
Determines which function is able to Write Tx data to the
UART transmit buffer.
00 = Disables
01 = Interrupt request or polling mode
10 = DMA mode
11 = Reserved

这里也选择 polling mode

register map summary

ULCONn 线控
UCONn 接受模式
UBRDIVn 设置速率 设置波特率
UFRACVALn 设置速率 波特率的分频值

UBRDIVn

28.6.1.11 UBRDIVn (n = 0 to 4)
 Base Address: 0x1380_0000, 0x1381_0000, 0x1382_0000, 0x1383_0000, 0x1384_0000
 Address = Base Address + 0x0028, Reset Value = 0x0000_0000

41522-xztmesobtld.png

28.6.1.12 UFRACVALn (n = 0 to 4)
 Base Address: 0x1380_0000, 0x1381_0000, 0x1382_0000, 0x1383_0000, 0x1384_0000
 Address = Base Address + 0x002C, Reset Value = 0x0000_0000

55433-ngbetb57d3.png

1. UART Baud-Rate Configuration
You can use the value stored in the Baud-rate divisor (UBRDIVn) and divisor fractional value (UFRACVALn) 
to determine the serial Tx/Rx clock rate (Baud rate) as:
DIV_VAL = UBRDIVn + UFRACVALn/16
or
DIV_VAL = (SCLK_UART/(bps  16))  1
Where, the divisor should be from 1 to (216 – 1).
By using UFRACVALn, you can generate the Baud rate more accurately.
For example, if the Baud rate is 115200 bps and SCLK_UART is 40 MHz, UBRDIVn and UFRACVALn are:
DIV_VAL = (40000000/(115200 * 16)) – 1
= 21.7 – 1 
= 20.7
UBRDIVn = 20 (integer part of DIV_VAL)
UFRACVALn/16 = 0.7 
Therefore, UFRACVALn = 11
2. Baud-Rate Error Tolerance
UART Frame error should be less than 1.87 % (3/160)
tUPCLK = (UBRDIVn + 1 + UFRACVAL/16)  16  1Frame/SCLK_UART 
tUPCLK = Real UART Clock
tEXTUARTCLK = 1Frame/baud-rate 
 tEXTUARTCLK = Ideal UART Clock 
UART error = (tUPCLK  tEXTUARTCLK)/tEXTUARTCLK  100 %
* 1Frame = start bit + data bit + parity bit + stop bit.
3. UART Clock and PCLK Relation
There is a constraint on the ratio of clock frequencies for PCLK to UARTCLK.
The frequency of UARTCLK must be no more than 5.5/3 times faster than the frequency of PCLK:
FUARTCLK  5.5/3  FPCLK
FUARTCLK = baudrate  16
这样就有足够的时间将接收到的数据写入接收FIFO。

时钟框图:
52953-3x8fel8rqxg.png

21736-h0s6x125i1q.png

PERI-L 左外设

UTXHn 指定传输缓冲区

28.6.1.9 UTXHn (n = 0 to 4)
 Base Address: 0x1380_0000, 0x1381_0000, 0x1382_0000, 0x1383_0000, 0x1384_0000
 Address = Base Address + 0x0020, Reset Value = 0x0000_0000
30323-brxi7kuz5cf.png

UTRSTATn 指定缓冲区状态

28.6.1.5 UTRSTATn (n = 0 to 4)
 Base Address: 0x1380_0000, 0x1381_0000, 0x1382_0000, 0x1383_0000, 0x1384_0000
 Address = Base Address + 0x0010, Reset Value = 0x0000_0000

检测状态是否为空
34358-cfnnkjv2kuh.png

设置不同模式

#define GPA1CON (*(volatile unsigned int *)*0x11400020)
#define ULCON2 (*(volatile unsigned int  *)*0x13820000)
#define UCON2 (*(volatile unsigned int   *)*0x13820004)
#define UBRDIV2 (*(volatile unsigned int *)*0x13820028)
#define UFRACVAL2 (*(volatile unsigned int *)*0x1382002C)
#define UTXH2      (*(volatile unsigned int *)0x13820020) 
#define UTRSTAT2   (*(volatile unsigned int *)0x13820010) 
void uart_init(void)
{
    //1. 配置pin GPA1_1 和 GPA1_0 为串口模式
    //*0x11400020 = 0x22
    GPA1CON = 0x22;
    //2. 设置窗口控制块
    //set data bit = 8, parity = none, stop = 1
    ULCON2 = 0x03;
    //3. set polling mode
    UCON2 = 0x05;
    /*
    设置波特率  = 115200
    DIV_VAL = (40000000/(115200  16)) – 1
            = 53.253
    UBRDIV2 = 50;
    UFRACVAL2 = 0.253 * 16 = 4
    */ 
    UBRDIV2 = 53;
    UFRACVAL2 
}

模拟输出

void putc(char c)
{
  while(1)
  {
        //只判断1号位是否为1
    if( UTRSTAT2&0x02)
        break;
  }
   UTXH2 = c;
}

int main(void) 
{
    uart_init()
    while(1)
    {
      putc('a');
      delay1s();
    }
    return 0;
}

Makefile

all:
    arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o start.o start.S
    arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o main.o main.c
    arm-none-linux-gnueabi-ld start.o main.o -Tmap.lds -o uart.elf
    arm-none-linux-gnueabi-objcopy -O binary  uart.elf uart.bin
    arm-none-linux-gnueabi-objdump -D uart.elf > uart.dis
clean:
    rm -rf *.bak start.o main.o uart.elf uart.bin uart.dis

先将两个文件编译

arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o start.o start.S
    arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o main.o main.c

指定链接脚本链接并转成二进制

arm-none-linux-gnueabi-ld start.o main.o -Tmap.lds -o uart.elf

map.lds

链接脚本指定最终目标文件地址
指定代码段地址

指定输出的格式
elf32文件格式以小端输出

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

最终输出的是arm系列cpu

OUTPUT_ARCH(arm)
ENTRY(_start) //链接后的第一条指令所在的地址
*(.text)  //系统自动安排下面的地址

点表示当前位置

. = 0x40008000;  /*指定链接的起始地址   */

. = ALIGN(4); 表示对齐

.text 表示代码段开始
.data 表示数据段开始

程序入口在start.s

中断异常向量表

        ldr        pc,_undefined_instruction  @0x04
        ldr        pc,_software_interrupt     
        ldr        pc,_prefetch_abort
        ldr        pc,_data_abort
        ldr        pc,_not_used
        ldr        pc,_irq
        ldr        pc,_fiq

_undefined_instruction: .word  _undefined_instruction
_software_interrupt:    .word  _software_interrupt
_prefetch_abort:        .word  _prefetch_abort
_data_abort:            .word  _data_abort
_not_used:                .word  _not_used
_irq:                    .word  _irq 
_fiq:                    .word  _fiq

96619-lhrbcv0vxdp.png

通过b指令跳转到c文件
69660-kqlvl0gk9n.png

c程序想要调用,需要声明全局

.global  delay1s 

和普通函数用法一样




Copyright © 2026 Y 版权所有.网站运行:13年238天21小时25分