文章目录
一、串口协议
串口是显控设备与信号处理板之间通信的主要接口,也是显控设备与其他设备、设备与设备之间的协议数据帧通信传输的重要接口。串口通信指串口按位(bit)发送和接收字节。尽管比特字节(byte)的串行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。串口通信协议是指规定了数据包的内容,内容包含了起始位、主体数据、校验位及停止位,双方需要约定一致的数据包格式才能正常收发数据的有关规范。串口通信协议是基于串口使得通信双方能够相互沟通信息的一种约定,其定义了双方遵循的协议数据帧格式和其传输方式。在串口通信中,常用的协议包括RS-232、RS-422和RS-485。
1、RS-232标准
RS-232是个人计算机上的通讯接口之一,由电子工业协会( Electronic Industries Association , EIA )所制定的异步传输标准接口。通常 RS-232接口以9个接脚( DB-9)或是25个接脚( DB-25)的型态出现,一般个人计算机上会有两组 RS-232接口,分别称为COM1和COM2。
RS-232-C是美国电子工业协会 EIA
( Electronic Industry Association )制定的一种串行物理接口标准。RS 是英文“推
荐标准”的缩写,232为标识号,C 表示修改次数。RS-232-C 总线标准设有25条信号线,包括一个主通道和一个辅助通道。在多数情况下主要使用主通道,对于一般双工通信,仅需几条信号线就可实现,如一条发送线TXD、一条接收线RXD及一条地线GND。
RS-232-C 标准规定的数据传输速率为每秒50、75、100、150、300、600、
1200、2400、4800、9600、19200波
特。
RS-232-C标准规定,驱动器允许有2500pF的电容负载,通信距离将受此电容限制,例如,采用150pF/ m 的通信电缆时,最大通信距离为15m;若每米电缆的电容量减小,通信距离可以增加。传输距离短的另一原因是 RS -232属单端信号传送,存在共地噪声和不能抑制共模干扰等问题,因此一般适用20m以内的通信。RS232规定在TXD和RXD上,用-3v到-15v表示逻辑“1”,用+3v到+15v表示逻辑“0”。
2、RS-485标准
RS-485协议标准由电信行业协会和电子工业联盟定义,使用该标准的通信网络能在远距离条件下以及电子噪声大的环境下有效传输信号,该标准允许连接多个收发器,即具有多站能力,这样可以利用单一的RS485接口方便地建立起一个设备网络。
RS-485标准规定采用差分信号进行数据传输,两线间的电压差为+2v到+6v表示逻辑“1”,两线间的电压差为﹣2v到﹣6v表示逻辑“0”;使用差分信号能有效地减少噪声信号的干扰,延长通信距离,RS485的通信距离可以达到1500m;RS485接口信号的电平比RS232降低了,所以不易损坏接口电路的芯片,且该电平与 TTL 电平兼容,可方便地与 TTL 电路连接。
但是RS-485总线标准对于通信网络中相关的应用层通信协议并没有做出明确的规定,则对于用户或者相关的开发者来说都可以建立对于自己的通信网络设备相关的所适用的高层通信协议标准-。同时由于在工业控制领域的应用RS-485总线通信网络的现场中,经常是以分散性的工业网络控制单元的数量居多并且各个工业设备之间的分布较远为主,将会导致在现场总线通信网络中存在各种各样的干扰使得整个通信网络的通信效率可靠性不高。
3、RS232、485电平与TTL电平的区别
TTL电平
TTL电平信号被利用得最多是因为通常数据表示采用二进制规定,+5V等价于逻辑“1”,0V等价于逻辑“0”,这被称做TTL(晶体管-晶体管逻辑电平)信号系统,这是计算机处理器控制的设备内部各部分之间通信的标准技术。
RS232和RS485、TTL的区别
1、RS232、RS485、TTL是指电平标准(电信号)
2、TTL电平标准 是 低电平为0,高电平为1(对地,标准数字电路逻辑)。
3、RS232电平标准 是 正电平为0,负电平为1(对地,正负6-15V皆可,甚至可以用高阻态)。
4、RS485与RS232类似,但是采用差分信号逻辑,更适合长距离、高速传输。
二、USART介绍
USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备。
USART收发模块一般分为三大部分:时钟发生器、数据发送器和接收器。控制寄存器为所有的模块共享。
时钟发生器由同步逻辑电路(在同步从模式下由外部时钟输入驱动)和波特率发生器组成。发送时钟引脚XCK仅用于同步发送模式下,
发送器部分由一个单独的写入缓冲器(发送UDR)、一个串行移位寄存器、校验位发生器和用于处理不同帧结构的控制逻辑电路构成。使用写入缓冲器,实现了连续发送多帧数据无延时的通信。
接收器是USART模块最复杂的部分,最主要的是时钟和数据接收单元。数据接收单元用作异步数据的接收。除了接收单元,接收器还包括校验位校验器、控制逻辑、移位寄存器和两级接收缓冲器(接收UDR)。接收器支持与发送器相同的帧结构,同时支持帧错误、数据溢出和校验错误的检测。
串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数据信息、停止信息,可能还有校验信息。USART 就是对这些传输参数有具体规定,当然也不是只有唯一一个参数值,很多参数值都可以自定义设置,只是增强它的兼容性。
STM32的串口通信接口有两种,分别是:UART(通用异步收发器)、USART(通用同步异步收发器)。对于大容量STM32F10x系列芯片,分别有3个USART和2个UART。
连接线路图
三、寄存器方式实现串口通信
1、创建项目并编写程序
点击项目新建工程
根据自己需要选取芯片,这里选用STM32F103C8
出现下图页面时,不做选择,直接×掉
在为文件目录下创建.s文件
选择.s文件,并为其命名
将如下代码写入新建.s文件中并保存。
;RCC寄存器地址映像
RCC_BASE EQU 0x40021000
RCC_CR EQU (RCC_BASE + 0x00)
RCC_CFGR EQU (RCC_BASE + 0x04)
RCC_CIR EQU (RCC_BASE + 0x08)
RCC_APB2RSTR EQU (RCC_BASE + 0x0C)
RCC_APB1RSTR EQU (RCC_BASE + 0x10)
RCC_AHBENR EQU (RCC_BASE + 0x14)
RCC_APB2ENR EQU (RCC_BASE + 0x18)
RCC_APB1ENR EQU (RCC_BASE + 0x1C)
RCC_BDCR EQU (RCC_BASE + 0x20)
RCC_CSR EQU (RCC_BASE + 0x24)
;AFIO寄存器地址映像
AFIO_BASE EQU 0x40010000
AFIO_EVCR EQU (AFIO_BASE + 0x00)
AFIO_MAPR EQU (AFIO_BASE + 0x04)
AFIO_EXTICR1 EQU (AFIO_BASE + 0x08)
AFIO_EXTICR2 EQU (AFIO_BASE + 0x0C)
AFIO_EXTICR3 EQU (AFIO_BASE + 0x10)
AFIO_EXTICR4 EQU (AFIO_BASE + 0x14)
;GPIOA寄存器地址映像
GPIOA_BASE EQU 0x40010800
GPIOA_CRL EQU (GPIOA_BASE + 0x00)
GPIOA_CRH EQU (GPIOA_BASE + 0x04)
GPIOA_IDR EQU (GPIOA_BASE + 0x08)
GPIOA_ODR EQU (GPIOA_BASE + 0x0C)
GPIOA_BSRR EQU (GPIOA_BASE + 0x10)
GPIOA_BRR EQU (GPIOA_BASE + 0x14)
GPIOA_LCKR EQU (GPIOA_BASE + 0x18)
;GPIO C口控制
GPIOC_BASE EQU 0x40011000
GPIOC_CRL EQU (GPIOC_BASE + 0x00)
GPIOC_CRH EQU (GPIOC_BASE + 0x04)
GPIOC_IDR EQU (GPIOC_BASE + 0x08)
GPIOC_ODR EQU (GPIOC_BASE + 0x0C)
GPIOC_BSRR EQU (GPIOC_BASE + 0x10)
GPIOC_BRR EQU (GPIOC_BASE + 0x14)
GPIOC_LCKR EQU (GPIOC_BASE + 0x18)
;串口1控制
USART1_BASE EQU 0x40013800
USART1_SR EQU (USART1_BASE + 0x00)
USART1_DR EQU (USART1_BASE + 0x04)
USART1_BRR EQU (USART1_BASE + 0x08)
USART1_CR1 EQU (USART1_BASE + 0x0c)
USART1_CR2 EQU (USART1_BASE + 0x10)
USART1_CR3 EQU (USART1_BASE + 0x14)
USART1_GTPR EQU (USART1_BASE + 0x18)
;NVIC寄存器地址
NVIC_BASE EQU 0xE000E000
NVIC_SETEN EQU (NVIC_BASE + 0x0010)
;SETENA寄存器阵列的起始地址
NVIC_IRQPRI EQU (NVIC_BASE + 0x0400)
;中断优先级寄存器阵列的起始地址
NVIC_VECTTBL EQU (NVIC_BASE + 0x0D08)
;向量表偏移寄存器的地址
NVIC_AIRCR EQU (NVIC_BASE + 0x0D0C)
;应用程序中断及复位控制寄存器的地址
SETENA0 EQU 0xE000E100
SETENA1 EQU 0xE000E104
;SysTick寄存器地址
SysTick_BASE EQU 0xE000E010
SYSTICKCSR EQU (SysTick_BASE + 0x00)
SYSTICKRVR EQU (SysTick_BASE + 0x04)
;FLASH缓冲寄存器地址映像
FLASH_ACR EQU 0x40022000
;SCB_BASE EQU (SCS_BASE + 0x0D00)
MSP_TOP EQU 0x20005000
;主堆栈起始值
PSP_TOP EQU 0x20004E00
;进程堆栈起始值
BitAlias_BASE EQU 0x22000000
;位带别名区起始地址
Flag1 EQU 0x20000200
b_flas EQU (BitAlias_BASE + (0x200*32) + (0*4))
;位地址
b_05s EQU (BitAlias_BASE + (0x200*32) + (1*4))
;位地址
DlyI EQU 0x20000204
DlyJ EQU 0x20000208
DlyK EQU 0x2000020C
SysTim EQU 0x20000210
;常数定义
Bit0 EQU 0x00000001
Bit1 EQU 0x00000002
Bit2 EQU 0x00000004
Bit3 EQU 0x00000008
Bit4 EQU 0x00000010
Bit5 EQU 0x00000020
Bit6 EQU 0x00000040
Bit7 EQU 0x00000080
Bit8 EQU 0x00000100
Bit9 EQU 0x00000200
Bit10 EQU 0x00000400
Bit11 EQU 0x00000800
Bit12 EQU 0x00001000
Bit13 EQU 0x00002000
Bit14 EQU 0x00004000
Bit15 EQU 0x00008000
Bit16 EQU 0x00010000
Bit17 EQU 0x00020000
Bit18 EQU 0x00040000
Bit19 EQU 0x00080000
Bit20 EQU 0x00100000
Bit21 EQU 0x00200000
Bit22 EQU 0x00400000
Bit23 EQU 0x00800000
Bit24 EQU 0x01000000
Bit25 EQU 0x02000000
Bit26 EQU 0x04000000
Bit27 EQU 0x08000000
Bit28 EQU 0x10000000
Bit29 EQU 0x20000000
Bit30 EQU 0x40000000
Bit31 EQU 0x80000000
;向量表
AREA RESET, DATA, READONLY
DCD MSP_TOP ;初始化主堆栈
DCD Start ;复位向量
DCD NMI_Handler ;NMI Handler
DCD HardFault_Handler ;Hard Fault Handler
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD SysTick_Handler ;SysTick Handler
SPACE 20 ;预留空间20字节
;代码段
AREA |.text|, CODE, READONLY
;主程序开始
ENTRY
;指示程序从这里开始执行
Start
;时钟系统设置
ldr r0, =RCC_CR
ldr r1, [r0]
orr r1, #Bit16
str r1, [r0]
;开启外部晶振使能
;启动外部8M晶振
ClkOk
ldr r1, [r0]
ands r1, #Bit17
beq ClkOk
;等待外部晶振就绪
ldr r1,[r0]
orr r1,#Bit17
str r1,[r0]
;FLASH缓冲器
ldr r0, =FLASH_ACR
mov r1, #0x00000032
str r1, [r0]
;设置PLL锁相环倍率为7,HSE输入不分频
ldr r0, =RCC_CFGR
ldr r1, [r0]
orr r1, #(Bit18 :OR: Bit19 :OR: Bit20 :OR: Bit16 :OR: Bit14)
orr r1, #Bit10
str r1, [r0]
;启动PLL锁相环
ldr r0, =RCC_CR
ldr r1, [r0]
orr r1, #Bit24
str r1, [r0]
PllOk
ldr r1, [r0]
ands r1, #Bit25
beq PllOk
;选择PLL时钟作为系统时钟
ldr r0, =RCC_CFGR
ldr r1, [r0]
orr r1, #(Bit18 :OR: Bit19 :OR: Bit20 :OR: Bit16 :OR: Bit14)
orr r1, #Bit10
orr r1, #Bit1
str r1, [r0]
;其它RCC相关设置
ldr r0, =RCC_APB2ENR
mov r1, #(Bit14 :OR: Bit4 :OR: Bit2)
str r1, [r0]
;IO端口设置
ldr r0, =GPIOC_CRL
ldr r1, [r0]
orr r1, #(Bit28 :OR: Bit29)
;PC.7输出模式,最大速度50MHz
and r1, #(~Bit30 & ~Bit31)
;PC.7通用推挽输出模式
str r1, [r0]
;PA9串口0发射脚
ldr r0, =GPIOA_CRH
ldr r1, [r0]
orr r1, #(Bit4 :OR: Bit5)
;PA.9输出模式,最大速度50MHz
orr r1, #Bit7
and r1, #~Bit6
;10:复用功能推挽输出模式
str r1, [r0]
ldr r0, =USART1_BRR
mov r1, #0x271
str r1, [r0]
;配置波特率-> 115200
ldr r0, =USART1_CR1
mov r1, #0x200c
str r1, [r0]
;USART模块总使能 发送与接收使能
;71 02 00 00 2c 20 00 00
;AFIO 参数设置
;Systick 参数设置
ldr r0, =SYSTICKRVR
;Systick装初值
mov r1, #9000
str r1, [r0]
ldr r0, =SYSTICKCSR
;设定,启动Systick
mov r1, #0x03
str r1, [r0]
;NVIC
;ldr r0, =SETENA0
;mov r1, 0x00800000
;str r1, [r0]
;ldr r0, =SETENA1
;mov r1, #0x00000100
;str r1, [r0]
;切换成用户级线程序模式
ldr r0, =PSP_TOP
;初始化线程堆栈
msr psp, r0
mov r0, #3
msr control, r0
;初始化SRAM寄存器
mov r1, #0
ldr r0, =Flag1
str r1, [r0]
ldr r0, =DlyI
str r1, [r0]
ldr r0, =DlyJ
str r1, [r0]
ldr r0, =DlyK
str r1, [r0]
ldr r0, =SysTim
str r1, [r0]
;主循环
main
ldr r0, =Flag1
ldr r1, [r0]
tst r1, #Bit1
;SysTick产生0.5s,置位bit 1
beq main ;0.5s标志还没有置位
;0.5s标志已经置位
ldr r0, =b_05s
;位带操作清零0.5s标志
mov r1, #0
str r1, [r0]
bl LedFlas
mov r0, #'H'
bl send_a_char
mov r0, #'e'
bl send_a_char
mov r0, #'l'
bl send_a_char
mov r0, #'l'
bl send_a_char
mov r0, #'o'
bl send_a_char
mov r0, #' '
bl send_a_char
mov r0, #'w'
bl send_a_char
mov r0, #'i'
bl send_a_char
mov r0, #'n'
bl send_a_char
mov r0, #'d'
bl send_a_char
mov r0, #'o'
bl send_a_char
mov r0, #'w'
bl send_a_char
mov r0, #'s'
bl send_a_char
mov r0, #'!'
bl send_a_char
mov r0, #'\n'
bl send_a_char
b main
;子程序 串口1发送一个字符
send_a_char
push {r0 - r3}
ldr r2, =USART1_DR
str r0, [r2]
b1
ldr r2, =USART1_SR
ldr r2, [r2]
tst r2, #0x40
beq b1
;发送完成(Transmission complete)等待
pop {r0 - r3}
bx lr
;子程序 led闪烁
LedFlas
push {r0 - r3}
ldr r0, =Flag1
ldr r1, [r0]
tst r1, #Bit0
;bit0 闪烁标志位
beq ONLED ;为0 打开led灯
;为1 关闭led灯
ldr r0, =b_flas
mov r1, #0
str r1, [r0]
;闪烁标志位置为0,下一状态为打开灯
;PC.7输出0
ldr r0, =GPIOC_BRR
ldr r1, [r0]
orr r1, #Bit7
str r1, [r0]
b LedEx
ONLED
;为0 打开led灯
ldr r0, =b_flas
mov r1, #1
str r1, [r0]
;闪烁标志位置为1,下一状态为关闭灯
;PC.7输出1
ldr r0, =GPIOC_BSRR
ldr r1, [r0]
orr r1, #Bit7
str r1, [r0]
LedEx
pop {r0 - r3}
bx lr
;异常程序
NMI_Handler
bx lr
HardFault_Handler
bx lr
SysTick_Handler
ldr r0, =SysTim
ldr r1, [r0]
add r1, #1
str r1, [r0]
cmp r1, #500
bcc TickExit
mov r1, #0
str r1, [r0]
ldr r0, =b_05s
;大于等于500次 清零时钟滴答计数器 设置0.5s标志位
;位带操作置1
mov r1, #1
str r1, [r0]
TickExit
bx lr
ALIGN
;通过用零或空指令NOP填充,来使当前位置与一个指定的边界对齐
END
点击下面图标
在output页面勾选Creat HEX File,然后进行编译构建生成HEX文件。
2、程序烧录
将STM32板子上的BOOT0置1,BOOT1置0,打开mcuisp,选择文件的路径,然后进行烧录:
3、串口调试
4、波形观察
在keil中进行相应的设置
点击如下图标,进入调试
选择逻辑分析仪,观察波形
点击Setup
添加要观察的引脚
得到波形图
四、使用HAL库实现串口通信
1、新建项目
选取自己的芯片,点击信息栏中的具体信息,然后点击start
配置时钟
设置USART1
点击Clock Configuration选择HSE和PLLCLK
填写项目名,选择路径,并完成设置
选择打开项目
在main.c中的while循环中写入如下代码:
char data[]="hello windows!\n";
HAL_UART_Transmit(&huart1, (uint8_t *)data, 15, 0xffff);
HAL_Delay(1000);
2、程序烧录
按照上面寄存器方式实现串口通信的方法进行烧录。
3、串口调试
选择串口,设置波特率,然后打开串口就可以进行串口通信了。
4、波形观察
五、总结
这次实验分别采用寄存器和HAL库的方式实现了串口通信,比较来看,寄存器方式繁琐复杂,而HAL库就简单了很多。总之两种方式都得到了正确结果。