ARM之串口的收发

 串口设备的裸机驱动开发
{
    1、明确需求: 谁(com2) 做什么(发送'S')
    2、看原理图:
        1)原理:  XuTXD2 ---> 数据发送   
        2)控制芯片: XuTXD2 ---》 GPA1_1------》uart(串口)控制器
                                    |
                                    |------> GPIO控制器(设置成串口发送的专用脚)
    3、芯片手册(寄存器)
        【GPIO】
        GPA1CON 0x11400020  [7:4] 0x2 = UART_2_TXD
        GPA1CON 0x11400020  [3:0] 0x2 = UART_2_RXD
        【uart】
        1)通过目录找到控制器章节
             28章节
        2)看看子章节和需求相关的部分
            概述看,需求功能相关看。
            a)串口有5路,4路是标准的串口(com2)。每个串口发送和接收buf。
            b)串口包含的内容:  波特率发生器,  发送接收单元,    停止位,校验位,数据位

            c)发送流程:    data-->fifo --> shifter --> txpin
                            |----人-||-------uart控制器-----|
            d)fifo: fifo:all bytes     no fifo:1 byte (选择)
            e)ULCONn: 设置数据位、校验位、停止位
            f)clk:UBRDIVn UFRACVALn

        3)看寄存器
            a)筛选寄存器(ctrl和config要,功能相关要,不确定的要)
            ULCON: 设置停止位、数据位、校验位
            UCON:全局控制
            UTXH:发送的fifo
            UBRDIV:波特率分频
            UFRACVAL:分频???

            b)细看寄存器,怎么实现需求
            ULCONn = 0x3;
            UCONn [3:2]  01 tx poll mode    [1:0]  01 rx poll mode    
            UTXHn:  把数据写入,就发送, 最多只能8位的数据
            URXHn:  从里面读数据 ok   最多只能读8位数据
            40MHZ = 40000000   40MHZ/(115200*16)-1    115200:波特率的位/秒
            UBRDIVn:  整数
            UFRACVALn: 小数*16 

}

all:
	arm-linux-gcc myadd.S -o start.o -c -g
	arm-linux-gcc main.c -o main.o -c -g
	arm-linux-ld  start.o main.o -o start.elf -Ttest.lds
	arm-linux-objcopy start.elf start.bin -O binary

汇编通用脚本 myadd.S:

.globl _start
_start: 
	b	reset
	ldr	pc, _undefined_instruction
	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:
	/* 设置cpu模式为SVC模式 */
	mrs	r0, cpsr
	bic	r0, r0, #0x1f  
	orr	r0, r0, #0xd3 
	msr	cpsr,r0

	/* 设置异常向量表起始地址 */
	ldr	r0, =0x41000000
	mcr	p15, 0, r0, c12, c0, 0	@Set VBAR

    /*用户需要设置的初始化*/
    ldr sp, stacktop  /*设置svc sp*/
    sub r6, sp , #64  /*计算user需要指向的栈顶地址*/

    /*切换到用户模式*/
	mrs	r0, cpsr
	bic	r0, r0, #0x1f  
	orr	r0, r0, #0x10 
	msr	cpsr,r0

    mov sp, r6  /*设置user sp*/

    /*跳转到应用程序*/
    bl main
stack: .space 64*8
stacktop: .word stack+64*8

连接汇编和c的脚本 test.lds:

ENTRY(_start)
SECTIONS{
	. = 0x41000000;
	.text : {
		start.o(.text)
		*(.text)
	}
	.data : {
		*(.data)
	}
	.bss : {
		*(.bss)	
	}
}

main.c:

#define GPA1CON      *(unsigned int volatile*)0x11400020
#define ULCON2       *(unsigned int volatile*)0x13820000
#define UCON2        *(unsigned int volatile*)0x13820004
#define UTXH2        *(unsigned int volatile*)0x13820020
#define URXH2        *(unsigned int volatile*)0x13820024
#define UBRDIV2      *(unsigned int volatile*)0x13820028
#define UFRACVAL2    *(unsigned int volatile*)0x1382002c
#define UTRSTAT2     *(unsigned int volatile*)0x13820010
//自定义睡眠函数
void delay(){
    int t = 0xfffff;
    while(t--);
}
void uart_init(){
    //波特率发生器
    //GPA1CON 0x11400020  [7:4] 0x2 = UART_2_TXD 发送
    GPA1CON = GPA1CON & ~(0xf<<4) | (0x2<<4);
    //GPA1CON 0x11400020  [3:0] 0x2 = UART_2_RXD 接收 
    GPA1CON = GPA1CON & ~(0xf<<0) | (0x2<<0);
    //指定数据位有几位,这里是8位
    ULCON2 = 0x3;
    //全局控制,清除0-5位待用,0x1<<2:轮询发送 <<0:轮询接收
    UCON2 = UCON2 & ~0x3f | (0x1<<2) | (0x1<<0);
//100MHZ = 100000000   100MHZ/(115200*16)-1	115200:波特率的位/秒
    UBRDIV2 = 53;
    UFRACVAL2 = 4;
}
void uart_send(char c){
    //检测有效数据,防止无效数据的发送
    //当传输buf无有效数据传输,且传输移位为空时,该位自动设置为1
    while( !(UTRSTAT2&(0x1<<2)) );
    UTXH2 = c;
}
void uart_str(char *s){

    while(*s!='\0'){
        uart_send(*s);
        s++;
    }
}
char uart_recv(){
    //检测有效数据
    //当接收buf含通过RXDn端口接收的有效数据时,自动将该位设置为1
    while( !(UTRSTAT2&0x1) );
    //接收数据位为8位
    return (URXH2 & 0xff);
}
void main()
{
#if 0
    char c = 'S';
    uart_init();
    uart_send(c);
#endif
#if 1
    char *s = "hello";
    uart_init();
    uart_str(s);
    //引入按键输入的字符
    while(1){
        char c = uart_recv();
        uart_send(c);
    }
#endif
    while(1);
} 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值