68.ARM裸机开发--USART操作(补充)

本文详细介绍了串口通讯的基本原理,包括不同类型的设备间通讯方式,如UART、I2C和SPI,并深入探讨了串口内部机制及编程方法。通过一个具体的实例,演示了如何使用C语言和汇编语言混合编程来实现串口输出字符,包括初始化、发送和接收字符的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.设备间通讯

  1. 单线
  2. 双线  uart    (全双工 异步)
  3. 双线  i2c     (半双工  同步)
  4. 三线  spi     (全双工  同步)
  5. 并行通讯  多根数据线 地址线,如内存

 

二.串口通讯协议

 

 

 

三. 串口内部机制

 

四.串口编程

1.初始化

    管脚设置为UART模式

    串口协议设置(奇偶校验为,数据位等)

    串口波特率设置

2.发送字符

    发送状态判断

    发送

3.接收字符后环回

    接收状态判断

    接收

 

五.汇编 c语言混合编程

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

脚本map.lds

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") //指定文件格式
OUTPUT_ARCH(arm)
ENTRY(_start) //连接之后的第一个地址是_start
SECTIONS
{
	. = 0x40008000;  /*指定链接的起始地址   */
	. = ALIGN(4);
	.text      :      //代码段开始
	{
		start.o(.text) //入口start.s
		*(.text)   //系统自动指定其他函数
	}
	. = ALIGN(4);
    .data : 		//	数据段开始
	{ *(.data) }
    . = ALIGN(4);
    .bss :
     { *(.bss) }
}

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,为c函数的调用提供栈空间********/
		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     //设置完栈后,跳转到C的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

main.c

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

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

#define  GPA1CON    (*(volatile unsigned int *)0x11400020)
#define  ULCON3     (*(volatile unsigned int *)0x13830000) 
#define  UCON3      (*(volatile unsigned int *)0x13830004) 
#define  UBRDIV3    (*(volatile unsigned int *)0x13830028) 
#define  UFRACVAL3  (*(volatile unsigned int *)0x1383002C) 
#define  UTXH3     (*(volatile unsigned int *)0x13830020) 
#define  UTRSTAT3   (*(volatile unsigned int *)0x13830010) 


void uart_init(void)
{
  //-----外: 配置管脚的工作模式
  GPA1CON |= 0x220000;  //配置GPA1_5 GPA1_4 为uart串口模式
  
  //-----内: 功能块设置
  //1.  uart 通讯协议格式的设置
  ULCON3 = 0x03;  //设置协议格式(  无校验位  1个停止位 8个数据位)
  UCON3 = 0x05;   //设置串口发送接收模式为polling模式
  
  /*2.  设置uart 的速度为115200
  DIV_VAL = (100000000/(115200 *16)) - 1 = 53.253
  UBRDIVn =  53
  UFRACVALn/16 = 0.253
  Therefore, UFRACVALn = 4
  */
  UBRDIV3 = 53;
  UFRACVAL3 = 4;
    
}

void putc(char c)
{
   while(1)
   {
      if(UTRSTAT3&0x02)  //检测发送是否为空
      {
         break;
      }
   }
   
   UTXH3 = c;  //发送字符
}

int main(void) 
{
  uart_init();
	while(1)
	{
      putc('f');
	  delay1s(); //调用汇编中的1s延时
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值