1,设备间 通讯实现
通信类型 | 线数 | 协议 | 工作模式 | 模型 | 速度 |
---|---|---|---|---|---|
串行通信 | 单线 | ||||
双线 | uart | 全双工 异步 | |||
双线 | i2c | 半双工 同步 | |||
三线 | spi | 全双工 同步 | |||
并行通信 | 多根数据线 地址线,如内存 |
1. 串口通信接收端通过循环检测高低电平来读取数据。若频率太高,波形就会变窄,接收端误识别几率就会增大
2. 所以同步通信引入了时钟线。同步通信速度较异步高
2,串口 UART
2.1,串口 UART 协议
2.1,UART 内部机制
3,例
3.1,代码—main.c
#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状态寄存器
void uart_init(void)
{
//4.设置波特率为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
//1.配置GPA1CON寄存器中的UART3 GPA1_4 UART_3_RXD
// GPA1_5 UART_3_TXD
GPA1CON &= 0xff00ffff;
GPA1CON |= 0x00220000;
//2.配置ULCON3寄存器 串口0 8位数据位,1位停止位,无奇偶校验
ULCON3 &= 0Xffffffc0;
ULCON3 |= 0x00000003;
//3.配置UCON3寄存器 通过轮询(polling)的模式读取串口数据 通过轮询(polling)的模式往串口写入数据数据
UCON3 &= 0xfffffff0;
UCON3 |= 0x00000005;
//4.设置波特率为115200
UBRDIV3 = 53;
UFRACVAL3 = 4;
//1.配置GPA1CON寄存器中的UART2 GPA1_0 UART_2_RXD
// GPA1_1 UART_2_TXD
GPA1CON &= 0xffffff00;
GPA1CON |= 0x00000022;
//2.配置ULCON2寄存器 串口2 8位数据位,1位停止位,无奇偶校验
ULCON2 &= 0Xffffffc0;
ULCON2 |= 0x00000003;
//3.配置UCON2寄存器 通过轮询(polling)的模式读取串口数据 通过轮询(polling)的模式往串口写入数据数据
UCON2 &= 0xfffffff0;
UCON2 |= 0x00000005;
UBRDIV2 = 53;
UFRACVAL2 = 4;
//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;
}
void uart0_putc(char c)
{
while(1)
{
if(UTRSTAT0 && 0X02) break;
}
UTXH0 = c;
}
char uart0_getc(char *c)
{
while(1)
{
if(UTRSTAT0 && 0X01) break;
}
*c = URXH0;
uart0_putc(*c);
return *c;
}
void uart2_putc(char c)
{
while(1)
{
if(UTRSTAT2 && 0X02) break;
}
UTXH2 = c;
}
void uart3_putc(char c)
{
while(1)
{
if(UTRSTAT3 && 0X02) break;
}
UTXH3 = c;
}
int main(void)
{
uart_init();
char c;
while(1)
{
uart0_getc(&c);
uart2_putc('b');
uart3_putc('c');
delay1s();
}
return 0;
}
3.2,编译脚本—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
3.3,汇编文件—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 /* 调用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
3.4,连接文件—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) }
}