您的位置:首页 > 其它

ARM体系结构及接口技术-05ARM通讯接口

2019-06-03 22:31 169 查看
版权声明: https://blog.csdn.net/Set_Mode/article/details/90760327

文章目录

  • 串口 UART 协议
  • Exynos4412 UART接口功能模块
  • Exynos4412 相关寄存器
  • UART 编程
  • ARM通讯接口

    串行通信的基本概念

    • 在通信领域内,有两种数据通信方式:并行通信和串行通信
    • 串口的数据传输是以串行方式进行的。
    • 串口在数据通信中,一次只传输一个比特的数据。
    • 串行数据的传输速度用bps或波特率来描述。

    串行通信涉及的常用术语(单工、半双工和全双工,异步方式与同步方式)

    • 单工(Simplex)
      特点:仅能进行一个方向的数据传送
    • 半双工(Half Duplex)
      特点:数据可以在两个方向上进行传送,但是这种传送绝不能同时进行
    • 全双工(Full Duplex)
      特点:能够在两个方向同时进行数据传送
      数据传输率
      每秒传输的二进制位数,单位为bps(bit per second )也称比特率

    多根数据线 地址线,如内存

    • 同步通信方式( Synchronous )所用的数据格式没有起始位、停止位,一次传送的字符个数可变。在传送前,先按照一定的格式将各种信息装配成一个包,该包包括供接收方识别用的同步字符一个或两个,其后紧跟着要传送的n个字符,再后就是校验字符。
    • 异步方式(Asynchronous):也称“起止同步式”。

    协议举例

    1. 串行通讯

      双线 uart (全双工 异步)

      双线 i2c (半双工 同步)

      三线 spi (全双工 同步)

    • 串口通信接收端通过循环检测高低电平来读取数据。若频率太高,波形就会变窄,接收端误识别几率就会增大
    • 所以同步通信引入了时钟线。同步通信速度较异步高
    1. 并行通讯:多根数据线 地址线,如内存
    • 硬件流控制
      如果打开串口硬件流控制后,串口A只有在nCTS被(串口B的nRTS)激活后才能把数据发送出去;
      当串口A可以接收数据时,激活nRTS

    串口 UART 协议

    Exynos4412 UART接口功能模块

    Exynos4412 相关寄存器

    UART 编程

    main.c

    /*
    
    功能:修改代码,实现除com2口外的别的一个com口输出字符显示
    
    */
    
    #define GPA1CON 	(*(volatile unsigned int *)0x11400020) 	//volatile 确保本条指令不会因编译器的优化而省略
    
    #define ULCON2 		(*(volatile unsigned int *)0x13820000) 	//串口2线控:数据位,停止位,奇偶校验位
    
    #define UCON2 		(*(volatile unsigned int *)0x13820004) 	//串口2读取控制:串口读的方式(如:轮询/中断等),写的方式
    
    #define UBRDIV2 	(*(volatile unsigned int *)0x13820028) 	//串口2波特率设置
    
    #define UFRACVAL2 	(*(volatile unsigned int *)0x1382002c) 	//串口2波特率设置
    
    #define UTXH2 		(*(volatile unsigned int *)0x13820020) 	//串口2发送缓存器
    
    #define URXH2 		(*(volatile unsigned int *)0x13820024) 	//串口2接受缓存器
    
    #define UTRSTAT2 	(*(volatile unsigned int *)0x13820010) 	//串口2状态寄存器
    
    #define GPA0CON 	(*(volatile unsigned int *)0x11400000) 	//volatile 确保本条指令不会因编译器的优化而省略
    
    #define ULCON0 		(*(volatile unsigned int *)0x13800000) 	//串口0线控:数据位,停止位,奇偶校验位
    
    #define UCON0 		(*(volatile unsigned int *)0x13800004) 	//串口0读取控制:串口读的方式(如:轮询/中断等),写的方式
    
    #define UBRDIV0 	(*(volatile unsigned int *)0x13800028) 	//串口0波特率设置
    
    #define UFRACVAL0 	(*(volatile unsigned int *)0x1380002c) 	//串口0波特率设置
    
    #define UTXH0 		(*(volatile unsigned int *)0x13800020) 	//串口0发送缓存器
    
    #define URXH0 		(*(volatile unsigned int *)0x13800024) 	//串口0接受缓存器
    
    #define UTRSTAT0 	(*(volatile unsigned int *)0x13800010) 	//串口0状态寄存器
    
    #define ULCON3 		(*(volatile unsigned int *)0x13830000) 	//串口3线控:数据位,停止位,奇偶校验位
    
    #define UCON3 		(*(volatile unsigned int *)0x13830004) 	//串口3读取控制:串口读的方式(如:轮询/中断等),写的方式
    
    #define UBRDIV3 	(*(volatile unsigned int *)0x13830028) 	//串口3波特率设置
    
    #define UFRACVAL3 	(*(volatile unsigned int *)0x1383002c) 	//串口3波特率设置
    
    #define UTXH3 		(*(volatile unsigned int *)0x13830020) 	//串口3发送缓存器
    
    #define URXH3 		(*(volatile unsigned int *)0x13830024) 	//串口3接受缓存器
    
    #define UTRSTAT3 	(*(volatile unsigned int *)0x13830010) 	//串口3状态寄存器
    
    typedef enum
    
    {
    
    DEVICE_UART_COM0 = 0,
    
    DEVICE_UART_COM1 = 1,
    1caa8
    
    DEVICE_UART_COM2 = 2,
    
    DEVICE_UART_COM3 = 3,
    
    MAX_DEVICE
    
    }DEVICE_LIST_E;
    
    /*
    
    设置波特率为115200
    
    //For example, if the Baud rate is 115200 bps and SCLK_UART is 100 MHz,UBRDIVn and UFRACVALn are:
    
    //DIV_VAL = (SCLK_UART/(bps * 16)) - 1
    
    //DIV_VAL = (100000000/(115200 * 16)) – 1
    
    //= 54.253 – 1
    
    //= 53.253
    
    //UBRDIVn = 53 (integer part of DIV_VAL)
    
    //UFRACVALn/16 = 0.253
    
    //Therefore, UFRACVALn = 4
    
    */
    
    void USART_Init(DEVICE_LIST_E Device_type)
    
    {
    
    if(Device_type == DEVICE_UART_COM0)
    
    {
    
    //1.配置GPA0CON寄存器中的UART0
    
    //GPA0_0  UART_0_RXD
    
    //GPA0_1  UART_0_TXD
    
    GPA0CON &= 0xffffff00;
    
    GPA0CON |= 0x00000022;
    
    //2.配置ULCON0寄存器
    
    //串口0 8位数据位,1位停止位,无奇偶校验
    
    ULCON0 &= 0Xffffffc0;
    
    ULCON0 |= 0x00000003;
    
    //3.配置UCON0寄存器
    
    //通过轮询(polling)的模式读取串口数据     通过轮询(polling)的模式往串口写入数据数据
    
    UCON0 &= 0xfffffff0;
    
    UCON0 |= 0x00000005;
    
    //4.设置波特率为115200
    
    UBRDIV0 = 53;
    
    UFRACVAL0 = 4;
    
    }
    
    if(Device_type == DEVICE_UART_COM2)
    
    {
    
    GPA1CON &= 0xffffff00;
    
    GPA1CON |= 0x00000022;
    
    ULCON2 &= 0Xffffffc0;
    
    ULCON2 |= 0x00000003;
    
    UCON2 &= 0xfffffff0;
    
    UCON2 |= 0x00000005;
    
    UBRDIV2 = 53;
    
    UFRACVAL2 = 4;
    
    }
    
    if(Device_type == DEVICE_UART_COM3)
    
    {
    
    GPA1CON &= 0xff00ffff;
    
    GPA1CON |= 0x00220000;
    
    ULCON3 &= 0Xffffffc0;
    
    ULCON3 |= 0x00000003;
    
    UCON3 &= 0xfffffff0;
    
    UCON3 |= 0x00000005;
    
    UBRDIV3 = 53;
    
    UFRACVAL3 = 4;
    
    }
    
    }
    
    void putc(DEVICE_LIST_E Device_type, char c)
    
    {
    
    switch(Device_type)
    
    {
    
    case DEVICE_UART_COM0:
    
    while(1)
    
    {
    
    if(UTRSTAT0 && 0X02)
    
    break;
    
    }
    
    UTXH0 = c;
    
    break;
    
    case DEVICE_UART_COM1:
    
    break;
    
    case DEVICE_UART_COM2:
    
    while(1)
    
    {
    
    if(UTRSTAT2 && 0X02)
    
    break;
    
    }
    
    UTXH2 = c;
    
    break;
    
    case DEVICE_UART_COM3:
    
    while(1)
    
    {
    
    if(UTRSTAT3 && 0X02)
    
    break;
    
    }
    
    break;
    
    default:
    
    break;
    
    }
    
    }
    
    char getc(void)
    
    {
    
    while(1)
    
    {
    
    if(UTRSTAT0 && 0X01) break;
    
    }
    
    return URXH0;
    
    }
    
    int main(void)
    
    {
    
    DEVICE_LIST_E vDevice = DEVICE_UART_COM0;
    
    USART_Init(vDevice);
    
    char c;
    
    while(1)
    
    {
    
    c = getc();
    
    delay1s();
    
    putc(vDevice,c);
    
    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

    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) 		/* 	生成文件支持arm系列的CPU     */
    ENTRY(_start) 			/*  连接后的第一条指令所在的地址是_start  */
    SECTIONS 		    	/*  目标文件的摆放    		*/
    {
    . = 0x40008000;  	/*  指定链接的起始地址   	*/
    . = ALIGN(4);    	/*  指令的对齐     			*/
    .text      : 	 	/*  代码段的开始     		*/
    {
    start.o(.text) 	/* 	start.o文件放在开始的位置   */
    *(.text)        /* 	其他目标文件自动分配位置    */
    }
    . = ALIGN(4);  		/* 	代码的对齐*/
    .data :
    { *(.data) }
    . = ALIGN(4);
    .bss :
    { *(.bss) }
    }
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: