串口通信小试牛刀
目录
- 串口通信小试牛刀
- 一、串口通信协议:RS-232
-
- 1.串口通信协议
- 2. RS-232
- 3.RS232电平与TTL电平的区别
- 4.USB/TTL转232模块(以CH340芯片模块为例)的工作原理
-
- 1.模块介绍
- 2.模块用途
- 3.硬件设计
- 二、stm32CubeMX的安装
-
- 1.配置环境变量
- 2.安装STM32CubeMX
- 3.初始化代码
- 4.修改代码并点亮流水灯
- 三、STM32的USART串口通讯程序
-
- 1.USART介绍
- 2.USART配置:
- 3.汇编实现
- 4.hel库实现
-
- 1.SRM32CubeMX
- 2.Keil
- 三、总结
- 四、参考文献
一、串口通信协议:RS-232
1.串口通信协议
串口通信指串口按位(bit)发送和接收字节。尽管比特字节(byte)的串行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。串口通信协议是指规定了数据包的内容,内容包含了起始位、主体数据、校验位及停止位,双方需要约定一致的数据包格式才能正常收发数据的有关规范。在串口通信中,常用的协议包括RS-232、RS-422和RS-485。
2. RS-232
RS-232标准接口(又称EIA RS-232)是常用的串行通信接口标准之一,它是由美国电子工业协会(EIA)联合贝尔系统公司、调制解调器厂家及计算机终端生产厂家于1970年共同制定,其全名是“数据终端设备( DTE)和数据通信设备(DCE)之间串行二进制数据交换接口技术标准”。1
RS-232(ANSI/EIA-232标准)是IBM-PC及其兼容机上的串行连接标准。可用于许多用途,比如连接鼠标、打印机或者Modem,同时也可以接工业仪器仪表。用于驱动和连线的改进,实际应用中RS-232的传输长度或者速度常常超过标准的值。RS-232只限于PC串口和设备间点对点的通信。RS-232串口通信最远距离是50英尺。
3.RS232电平与TTL电平的区别
-
TTL电平标准:
- 输出L:<0.8V;H:>2.4V。
- 输入L:<1.2V;H:>2.0V。
- TTL器件输出低电平要小于0.8V,高电平要大于2.4V。输入,低于1.2V就认为是0,高于2.0就认为是1。于是TTL电平的输入低电平的噪声容限就只有(0.8-0)/2=0.4V,高电平的噪声容限为(5-2.4)/2=1.3V。
-
RS232标准:
- 逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V,注意电平的定义反相了一次。RS232可做到双向传输,全双工通讯,为异步数据传输方式,最高传输速率可达到20Kbps。
-
RS232电平与TTL电平的区别:
- 电平的上限和下限定义不一样,CMOS具有更大的抗噪区域。 同是5伏供电的话,ttl一般是1.7V和3.5V的样子,CMOS一般是2.2V,2.9V的样子,不准确,仅供参考。
- 电流驱动能力不一样,ttl一般提供25毫安的驱动能力,而CMOS一般在10毫安左右。
- 需要的电流输入大小也不一样,一般ttl需要2.5毫安左右,CMOS几乎不需要电流输入。
- 很多器件都是兼容TTL和CMOS的,datasheet会有说明。如果不考虑速度和性能,一般器件可以互换。但是需要注意有时候负载效应可能引起电路工作不正常,因为有些ttl电路需要下一级的输入阻抗作为负载才能正常工作。
4.USB/TTL转232模块(以CH340芯片模块为例)的工作原理
1.模块介绍
-
模块特点
CH340C USB转TTL模块以CH340C芯片为核心,内部自带晶振,最高波特率可达2Mbps,软件兼容CH341驱动,过流保护,引出相应的通讯接口与电源接口,通讯接口带有指示灯指示工作状态,通讯稳定,体积小。- 全速USB驱动,兼容USB2.0
- 硬件全双工串口,内置收发缓冲区
- 支持波特率50bps~2Mbps
- 输出TTL电平3.3V,兼容5V的IO电平
-
模块接口引脚
Symbol(符号) | Type (类型) | Deion(描述) |
---|---|---|
TXD | 输出 | 串行数据输出口 |
RXD | 输入 | 串行数据输出口 |
GND | 电源 | 接地引脚 |
3V3 | 电源 | 3.3V电源输出引脚(最高250mA) |
5V | 电源 | 3.3V电源输出引脚(最高250mA) |
DTS | 输出 | MODEM联络输出信号,请求发送 |
DTR | 输出 | MODEM联络输出信号,数据终端就绪 |
输入输出接口引脚均带有LED指示灯
电源接口引脚中,5V的接口引脚带有LED指示灯
2.模块用途
电脑USB端是USB电平,单片机的信号是TTL电平,两者的电平不同是无法进行通讯的,需要通过转换才能实现相互通讯。CH340C USB 转TTL模块就是实现USB电平与TTL电平相互转换的模块。
- USB:采用VCC、GND、D+、D-传输,电脑上的插口就是USB接口。
- TTL:一般指单片机的逻辑电平,不同单片的供电的系统TTL的电平不一样,3.3V单片的TTL电平就是:高电平3.3V(逻辑1),低电平0V(逻辑0)。
-
单片机与上位机的通讯
在调试单片机程序的时候,想了解程序的执行情况或相关信息,一般简单的做法就是用串口把信息发送给电脑,电脑接收到再通过上位机(串口调试助手)显示出来。但是单片机串口发送的信号是TTL电平,电脑能接收到的信号是USB电平,两者无法直接通讯。USB转TTL模块可以把串口发送的TTL信号转换成USB信号再发送给电脑,电脑就可以接收到单片机发送过来的信号并在上位机(串口调试助手)上显示出来。
-
单片机的ISP串口程序下载
大部分单片机都可以使用串口的方式通过相应的上位机软件来下载程序,但是电脑的USB出来的信号是USB信号,单片机是无法识别USB信号的,需要通过USB转TTL模块把USB信号转换成TTL信号才能将程序下载到单片机中。
-
MODEMD的固件升级
有些MODEM可以使用串口升级固件,在模块中也引出了RTS,DTR两个MODEM信号输出接口,并带有相应的指示灯指示状态。
3.硬件设计
硬件电路设计主要介绍以CH340C芯片为核心,设计出一个USB转TTL的模块(也就是该模块)。主要包括电源的设计、功能的设计等,其中选用的器件规格型号可以参考产品手册的BOM表。
- CH340C芯片引脚功能表
引脚序号 | 引脚名称 | 类型 | 引脚说明 |
---|---|---|---|
1 | GND | 电源 | 公共接地端,直接连到USB总线的地线 |
3 | RXD | 输入 | 串行数据输入 |
4 | V3 | 电源 | 在3.3V电源电源电压时连接VCC输入外部电源 ; 在5V电源电压时外接容量为0.1uF退藕电容 |
5 | D+ | USB信号 | 直接连接到USB总线的D+数据线 |
6 | D- | USB信号 | 直接连接到USB总线的D-数据线 |
7 | XI | 输入 | CH340C内部自带晶振,必须悬空 |
8 | XO | 输出 | CH340C内部自带晶振,必须悬空 |
9 | CTS# | 输入 | MODEM联络输入信号,清除发送,低(高)有效 |
10 | 输入 | 输入 | MODEM联络输入信号,数据装置就绪,低(高)有效 |
11 | RI# | 输入 | MODEM联络输入信号,振铃提示,低(高)有效 |
12 | DCD# | 输入 | MODEM联络输入信号,载波检测,低(高)有效 |
13 | DCD# | 输出 | MODEM联络输入信号,数据终端就绪,低(高)有效 |
14 | RTS# | 输出 | MODEM联络输入信号,请求发送,低(高)有效 |
15 | R232 | 电源 | 辅助RS232使能,高有效,内置下拉 |
16 | VCC | 电源 | 正电源输入端,需外接0.1uF电源退藕电容 |
-
模块的电源设计
- 在CH340C的引脚功能表中红色部分是电源相关的引脚。对于不同电压供电系统的TTL电平是不一样的,大部分的系统是5V或3.3V供电。一般5V的系统是兼容3.3V的TTL电平的,但是3.3V系统是不兼容5V的。为了是能兼容3.3V与5V的系统,模块的电源使用3.3V电源供电。
- 电脑的USB接口电源输出时5V,最大电流是500mA,在电路中为了防止意外的误操作,在5V的电源端加了一个0.5A,6V的保险丝F1,当电压超过6V或电流超过0.5A保险丝就会断开对电路进行保护。
- USB输出的电压是5V,而CH340C的芯片采用3.3V供电,为了使模块的供电为3.3V,在电路中加入了一个LDO(低压差线性稳压器)U2,它可以把5V稳压成3.3V,然后对CH340C进行供电(根据手册要求V3引脚也要接3.3V的电源)。每一个电源的输入端都会加上一个0.1uF的滤波电容。
在模块引出的接口中: - 5V:USB的电源输出,电压为5V,电流最大可达500mA
- 3V3:5V经过LDO稳压后得到的3.3V电压,电流最大可达25mA
- GND:USB的GND
-
模块的USB转TTL电路设计
在CH340C的引脚功能表中蓝色部分是信号相关的引脚,黑色部分的与设计无关的引脚,全部悬空。CH340C芯片的D-,D+与USB的D-,D+连接到一起作为USB电平的信号连接,同时引出TTL电平信号的接口TXD与RXD,还有两个MODEM输出信号接口RTS与DTR。
-
模块的指示灯电路设计
为了检测模块是否通电正常,在5V的输入端设计了一个指示灯LED1(红色),该等亮表示模块已经上电。通讯时需要了解数据的收发情况,在TXD,RXD数据接口中分别接入了LED2(蓝色),LED3(绿色)指示灯。当模块到数据时,RXD的指示灯就会亮;模块发送数据时TXD的指示灯就会亮。另外引出的RTS与DTR信号接口也设计了LED4(黄色),LED5(绿色)指示灯。
因为TXD,RXD,RTS,DTR接口都是从CH340C芯片管脚印出来的,CH340C是3.3V供电,所以设计对应的指示灯的电源应该选择3.3V。TXD与RXD在CH340C中空闲时(没有发生数据传输)是高电平的,对应的指示灯状态时灭的,只有发生数据传输时指示灯才会亮。RTS与DTR接口时CH340C的MODEM输出信号接口,对应的指示灯在用不同的上位机软件它们的亮灭是不确定的。
二、stm32CubeMX的安装
1.配置环境变量
云盘下载:这里使用了这个博客提供的云盘地址
https://blog.csdn.net/Brendon_Tan/article/details/107685563
但是需要Java环境支撑,去官网 https://www.java.com/zh_CN/download/windows-64bit.jsp下载之后遇到了的问题,搜索之后发现中文版的官网只支持32位的下载,这里需要把中文版网址的zh_CN改成en,访问英文版的官网点击download
找到
选择x64的版本
就可以安装STM32CubeMX了。
(https://blog.csdn.net/zjszd/article/details/120933702)3.初始化代码
- File-New Project
- 之后会在线下载一些东西
- 选择型号STM32F103C8,选中之后点击start project
- System Core-SYS-debug-Serial Wire
- System Core-RCC-High Speed Clock-Crystal/Ceramic Resonator
- 勾选Clock Condigiguration-PLLCLK
- Pinout ViewPA0,PB9,PC15设置GPIO_Output
- Project Manager- Project -Toolchain / IDE-MDK-ARM
- Project Manager- Code Generator-Generated files-勾选第一个
- Generator Code
- Open Project
4.修改代码并点亮流水灯
- 打开main.c文件,在while函数里面添加实现功能的代码
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);//PA0
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);//PA0
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);//PC15
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);//PC15
HAL_Delay(1000);//1s
- 编译,没有错误
- 在debug里修改Diog.dll和Parameter
debug输出波形图
- 打开McuFly,运行
三、STM32的USART串口通讯程序
1.USART介绍
- 百度百科:
- (Universal Synchronous/Asynchronous Receiver/Transmitter)
- 通用同步/异步串行接收/发送器
- USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备。
- 主要特点
- 全双工操作(相互独立的接收数据和发送数据);
- 同步操作时,可主机时钟同步,也可从机时钟同步;
- 独立的高精度波特率发生器,不占用定时/计数器;
- 支持5、6、7、8和9位数据位,1或2位停止位的串行数据帧结构;
- 由硬件支持的奇偶校验位发生和检验;
- 数据溢出检测;
- 帧错误检测;
- 包括错误起始位的检测噪声滤波器和数字低通滤波器;
- 三个完全独立的中断,TX发送完成、TX发送数据寄存器空、RX接收完成;
- 支持多机通信模式;
- 支持倍速异步通信模式。
- 功能引脚
引脚 | 功能 |
---|---|
TX | 发送数据输出引脚 |
RX | 接收数据输入引脚 |
SW_RX | 数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。 |
nRTS | 请求以发送(Request To Send), n 表示低电平有效。如果使能 RTS 流控制,当USART 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。 |
USART | 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。 |
nRTS | 将被设置为高电平。该引脚只适用于硬件流控制。 |
nCTS | 清除以发送(Clear To Send), n 表示低电平有效。如果使能 CTS 流控制,发送器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。 |
SCLK | 发送器时钟输出引脚。这个引脚仅适用于同步模式。 |
2.USART配置:
- STM32在只有一个中断的情况下,仍然需要配置优先级,其作用是使能某条中断的触发通道。STM32的中断有至多两个层次,分别是抢占优先级(主优先级)和子优先级(从优先级),而整个优先级设置参数的长度为4位,因此需要首先划分抢占优先级位数和子优先级位数,通过
NVIC_PriorityGroupConfig()
实现; - 特定设备的中断优先级NVIC的属性包含在结构体NVIC_InitTypeDef中,其中字段
NVIC_IRQChannel
包含了设备的中断向量,保存在启动代码中;字段NVIC_IRQChannelPreemptionPriority
为主优先级,NVIC_IRQChannelSubPriority
为从优先级,取值的范围应根据位数划分的情况而定;最后NVIC_IRQChannelCmd
字段是是否使能,一般置为ENABLE。最后通过NVIC_Init()
来使能这一中断向量。
3.汇编实现
-
打开Keil-Project-new peoject
-
新建文件
-
芯片依旧选择STM32F103C8
- 新建main.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]
;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]
;切换成用户级线程序模式
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]
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, #'\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
;异常程序
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填充,来使当前位置与一个指定的边界对齐
EN
-
build
这里又有错误,是版本问题,修改一下就好
忘了生成.hex文件
-
McuFly
-
调试
成功 -
观察波形
debug修改相关设置
点开波形图添加寄存器
4.hel库实现
1.SRM32CubeMX
-
File-New Project,选择型号STM32F103C8,选中之后点击start project
-
System Core-RCC-High Speed Clock-Crystal/Ceramic Resonator
-
A->Z-USART1-Asynchronous
-
勾选Clock Condigiguration-PLLCLK
-
新建文件名
Project Manager- Project -Toolchain / IDE-MDK-ARM
Application Structure-Basic
-
Project Manager- Code Generator-Generated files-勾选第一个
-
Generator Code
-
Open Project
2.Keil
- 在main.c文件的while函数中添加代码
char data[]="hello windows!\n";
HAL_UART_Transmit(&huart1, (uint8_t *)data, 15, 0xffff);
HAL_Delay(1000);
- build
- McuFly
- 调试
- 分析波形
- debug
- setup
- 波形图
- debug
三、总结
这次作业我学习了解串口协议和RS-232标准,以及RS232电平与TTL电平的区别,以及USB/TTL转232的工作原理。通过后面的实验汇编语言和STM32CubeMX做两个项目,我了解了STM32CubeMX的基本操作方法,如何建立.hex文件等,比起汇编语言实现,它要方便快捷很多,了解了如何使用Keil波形图分析。当然实验过程中也遇到了很多问题,在自己查阅资料和同学的帮助下都成功地解决了。
四、参考文献
http://www.elecfans.com/emb/jiekou/20171101573461.html
https://www.sohu.com/a/168891691_669755
https://blog.csdn.net/Mark_md/article/details/108597911
https://blog.csdn.net/qq_43279579/article/details/112233696
https://blog.csdn.net/vic_to_ry/article/details/110451036
https://www.cnblogs.com/yangguang-it/p/7070787.html
- 李永忠主编.现代微机原理与接口技术:西安电子科技大学出版社,2013.10 ↩︎
本文转自 https://blog.csdn.net/zjszd/article/details/120933702,如有侵权,请联系删除。
版权声明:本文为CSDN博主「weixin_45937995」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45937995/article/details/122500944
串口通信小试牛刀
目录
- 串口通信小试牛刀
- 一、串口通信协议:RS-232
-
- 1.串口通信协议
- 2. RS-232
- 3.RS232电平与TTL电平的区别
- 4.USB/TTL转232模块(以CH340芯片模块为例)的工作原理
-
- 1.模块介绍
- 2.模块用途
- 3.硬件设计
- 二、stm32CubeMX的安装
-
- 1.配置环境变量
- 2.安装STM32CubeMX
- 3.初始化代码
- 4.修改代码并点亮流水灯
- 三、STM32的USART串口通讯程序
-
- 1.USART介绍
- 2.USART配置:
- 3.汇编实现
- 4.hel库实现
-
- 1.SRM32CubeMX
- 2.Keil
- 三、总结
- 四、参考文献
一、串口通信协议:RS-232
1.串口通信协议
串口通信指串口按位(bit)发送和接收字节。尽管比特字节(byte)的串行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。串口通信协议是指规定了数据包的内容,内容包含了起始位、主体数据、校验位及停止位,双方需要约定一致的数据包格式才能正常收发数据的有关规范。在串口通信中,常用的协议包括RS-232、RS-422和RS-485。
2. RS-232
RS-232标准接口(又称EIA RS-232)是常用的串行通信接口标准之一,它是由美国电子工业协会(EIA)联合贝尔系统公司、调制解调器厂家及计算机终端生产厂家于1970年共同制定,其全名是“数据终端设备( DTE)和数据通信设备(DCE)之间串行二进制数据交换接口技术标准”。1
RS-232(ANSI/EIA-232标准)是IBM-PC及其兼容机上的串行连接标准。可用于许多用途,比如连接鼠标、打印机或者Modem,同时也可以接工业仪器仪表。用于驱动和连线的改进,实际应用中RS-232的传输长度或者速度常常超过标准的值。RS-232只限于PC串口和设备间点对点的通信。RS-232串口通信最远距离是50英尺。
3.RS232电平与TTL电平的区别
-
TTL电平标准:
- 输出L:<0.8V;H:>2.4V。
- 输入L:<1.2V;H:>2.0V。
- TTL器件输出低电平要小于0.8V,高电平要大于2.4V。输入,低于1.2V就认为是0,高于2.0就认为是1。于是TTL电平的输入低电平的噪声容限就只有(0.8-0)/2=0.4V,高电平的噪声容限为(5-2.4)/2=1.3V。
-
RS232标准:
- 逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V,注意电平的定义反相了一次。RS232可做到双向传输,全双工通讯,为异步数据传输方式,最高传输速率可达到20Kbps。
-
RS232电平与TTL电平的区别:
- 电平的上限和下限定义不一样,CMOS具有更大的抗噪区域。 同是5伏供电的话,ttl一般是1.7V和3.5V的样子,CMOS一般是2.2V,2.9V的样子,不准确,仅供参考。
- 电流驱动能力不一样,ttl一般提供25毫安的驱动能力,而CMOS一般在10毫安左右。
- 需要的电流输入大小也不一样,一般ttl需要2.5毫安左右,CMOS几乎不需要电流输入。
- 很多器件都是兼容TTL和CMOS的,datasheet会有说明。如果不考虑速度和性能,一般器件可以互换。但是需要注意有时候负载效应可能引起电路工作不正常,因为有些ttl电路需要下一级的输入阻抗作为负载才能正常工作。
4.USB/TTL转232模块(以CH340芯片模块为例)的工作原理
1.模块介绍
-
模块特点
CH340C USB转TTL模块以CH340C芯片为核心,内部自带晶振,最高波特率可达2Mbps,软件兼容CH341驱动,过流保护,引出相应的通讯接口与电源接口,通讯接口带有指示灯指示工作状态,通讯稳定,体积小。- 全速USB驱动,兼容USB2.0
- 硬件全双工串口,内置收发缓冲区
- 支持波特率50bps~2Mbps
- 输出TTL电平3.3V,兼容5V的IO电平
-
模块接口引脚
Symbol(符号) | Type (类型) | Deion(描述) |
---|---|---|
TXD | 输出 | 串行数据输出口 |
RXD | 输入 | 串行数据输出口 |
GND | 电源 | 接地引脚 |
3V3 | 电源 | 3.3V电源输出引脚(最高250mA) |
5V | 电源 | 3.3V电源输出引脚(最高250mA) |
DTS | 输出 | MODEM联络输出信号,请求发送 |
DTR | 输出 | MODEM联络输出信号,数据终端就绪 |
输入输出接口引脚均带有LED指示灯
电源接口引脚中,5V的接口引脚带有LED指示灯
2.模块用途
电脑USB端是USB电平,单片机的信号是TTL电平,两者的电平不同是无法进行通讯的,需要通过转换才能实现相互通讯。CH340C USB 转TTL模块就是实现USB电平与TTL电平相互转换的模块。
- USB:采用VCC、GND、D+、D-传输,电脑上的插口就是USB接口。
- TTL:一般指单片机的逻辑电平,不同单片的供电的系统TTL的电平不一样,3.3V单片的TTL电平就是:高电平3.3V(逻辑1),低电平0V(逻辑0)。
-
单片机与上位机的通讯
在调试单片机程序的时候,想了解程序的执行情况或相关信息,一般简单的做法就是用串口把信息发送给电脑,电脑接收到再通过上位机(串口调试助手)显示出来。但是单片机串口发送的信号是TTL电平,电脑能接收到的信号是USB电平,两者无法直接通讯。USB转TTL模块可以把串口发送的TTL信号转换成USB信号再发送给电脑,电脑就可以接收到单片机发送过来的信号并在上位机(串口调试助手)上显示出来。
-
单片机的ISP串口程序下载
大部分单片机都可以使用串口的方式通过相应的上位机软件来下载程序,但是电脑的USB出来的信号是USB信号,单片机是无法识别USB信号的,需要通过USB转TTL模块把USB信号转换成TTL信号才能将程序下载到单片机中。
-
MODEMD的固件升级
有些MODEM可以使用串口升级固件,在模块中也引出了RTS,DTR两个MODEM信号输出接口,并带有相应的指示灯指示状态。
3.硬件设计
硬件电路设计主要介绍以CH340C芯片为核心,设计出一个USB转TTL的模块(也就是该模块)。主要包括电源的设计、功能的设计等,其中选用的器件规格型号可以参考产品手册的BOM表。
- CH340C芯片引脚功能表
引脚序号 | 引脚名称 | 类型 | 引脚说明 |
---|---|---|---|
1 | GND | 电源 | 公共接地端,直接连到USB总线的地线 |
3 | RXD | 输入 | 串行数据输入 |
4 | V3 | 电源 | 在3.3V电源电源电压时连接VCC输入外部电源 ; 在5V电源电压时外接容量为0.1uF退藕电容 |
5 | D+ | USB信号 | 直接连接到USB总线的D+数据线 |
6 | D- | USB信号 | 直接连接到USB总线的D-数据线 |
7 | XI | 输入 | CH340C内部自带晶振,必须悬空 |
8 | XO | 输出 | CH340C内部自带晶振,必须悬空 |
9 | CTS# | 输入 | MODEM联络输入信号,清除发送,低(高)有效 |
10 | 输入 | 输入 | MODEM联络输入信号,数据装置就绪,低(高)有效 |
11 | RI# | 输入 | MODEM联络输入信号,振铃提示,低(高)有效 |
12 | DCD# | 输入 | MODEM联络输入信号,载波检测,低(高)有效 |
13 | DCD# | 输出 | MODEM联络输入信号,数据终端就绪,低(高)有效 |
14 | RTS# | 输出 | MODEM联络输入信号,请求发送,低(高)有效 |
15 | R232 | 电源 | 辅助RS232使能,高有效,内置下拉 |
16 | VCC | 电源 | 正电源输入端,需外接0.1uF电源退藕电容 |
-
模块的电源设计
- 在CH340C的引脚功能表中红色部分是电源相关的引脚。对于不同电压供电系统的TTL电平是不一样的,大部分的系统是5V或3.3V供电。一般5V的系统是兼容3.3V的TTL电平的,但是3.3V系统是不兼容5V的。为了是能兼容3.3V与5V的系统,模块的电源使用3.3V电源供电。
- 电脑的USB接口电源输出时5V,最大电流是500mA,在电路中为了防止意外的误操作,在5V的电源端加了一个0.5A,6V的保险丝F1,当电压超过6V或电流超过0.5A保险丝就会断开对电路进行保护。
- USB输出的电压是5V,而CH340C的芯片采用3.3V供电,为了使模块的供电为3.3V,在电路中加入了一个LDO(低压差线性稳压器)U2,它可以把5V稳压成3.3V,然后对CH340C进行供电(根据手册要求V3引脚也要接3.3V的电源)。每一个电源的输入端都会加上一个0.1uF的滤波电容。
在模块引出的接口中: - 5V:USB的电源输出,电压为5V,电流最大可达500mA
- 3V3:5V经过LDO稳压后得到的3.3V电压,电流最大可达25mA
- GND:USB的GND
-
模块的USB转TTL电路设计
在CH340C的引脚功能表中蓝色部分是信号相关的引脚,黑色部分的与设计无关的引脚,全部悬空。CH340C芯片的D-,D+与USB的D-,D+连接到一起作为USB电平的信号连接,同时引出TTL电平信号的接口TXD与RXD,还有两个MODEM输出信号接口RTS与DTR。
-
模块的指示灯电路设计
为了检测模块是否通电正常,在5V的输入端设计了一个指示灯LED1(红色),该等亮表示模块已经上电。通讯时需要了解数据的收发情况,在TXD,RXD数据接口中分别接入了LED2(蓝色),LED3(绿色)指示灯。当模块到数据时,RXD的指示灯就会亮;模块发送数据时TXD的指示灯就会亮。另外引出的RTS与DTR信号接口也设计了LED4(黄色),LED5(绿色)指示灯。
因为TXD,RXD,RTS,DTR接口都是从CH340C芯片管脚印出来的,CH340C是3.3V供电,所以设计对应的指示灯的电源应该选择3.3V。TXD与RXD在CH340C中空闲时(没有发生数据传输)是高电平的,对应的指示灯状态时灭的,只有发生数据传输时指示灯才会亮。RTS与DTR接口时CH340C的MODEM输出信号接口,对应的指示灯在用不同的上位机软件它们的亮灭是不确定的。
二、stm32CubeMX的安装
1.配置环境变量
云盘下载:这里使用了这个博客提供的云盘地址
https://blog.csdn.net/Brendon_Tan/article/details/107685563
但是需要Java环境支撑,去官网 https://www.java.com/zh_CN/download/windows-64bit.jsp下载之后遇到了的问题,搜索之后发现中文版的官网只支持32位的下载,这里需要把中文版网址的zh_CN改成en,访问英文版的官网点击download
找到
选择x64的版本
就可以安装STM32CubeMX了。
(https://blog.csdn.net/zjszd/article/details/120933702)3.初始化代码
- File-New Project
- 之后会在线下载一些东西
- 选择型号STM32F103C8,选中之后点击start project
- System Core-SYS-debug-Serial Wire
- System Core-RCC-High Speed Clock-Crystal/Ceramic Resonator
- 勾选Clock Condigiguration-PLLCLK
- Pinout ViewPA0,PB9,PC15设置GPIO_Output
- Project Manager- Project -Toolchain / IDE-MDK-ARM
- Project Manager- Code Generator-Generated files-勾选第一个
- Generator Code
- Open Project
4.修改代码并点亮流水灯
- 打开main.c文件,在while函数里面添加实现功能的代码
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);//PA0
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);//PA0
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);//PC15
HAL_Delay(1000);//1s
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);//PC15
HAL_Delay(1000);//1s
- 编译,没有错误
- 在debug里修改Diog.dll和Parameter
debug输出波形图
- 打开McuFly,运行
三、STM32的USART串口通讯程序
1.USART介绍
- 百度百科:
- (Universal Synchronous/Asynchronous Receiver/Transmitter)
- 通用同步/异步串行接收/发送器
- USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备。
- 主要特点
- 全双工操作(相互独立的接收数据和发送数据);
- 同步操作时,可主机时钟同步,也可从机时钟同步;
- 独立的高精度波特率发生器,不占用定时/计数器;
- 支持5、6、7、8和9位数据位,1或2位停止位的串行数据帧结构;
- 由硬件支持的奇偶校验位发生和检验;
- 数据溢出检测;
- 帧错误检测;
- 包括错误起始位的检测噪声滤波器和数字低通滤波器;
- 三个完全独立的中断,TX发送完成、TX发送数据寄存器空、RX接收完成;
- 支持多机通信模式;
- 支持倍速异步通信模式。
- 功能引脚
引脚 | 功能 |
---|---|
TX | 发送数据输出引脚 |
RX | 接收数据输入引脚 |
SW_RX | 数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。 |
nRTS | 请求以发送(Request To Send), n 表示低电平有效。如果使能 RTS 流控制,当USART 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。 |
USART | 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。 |
nRTS | 将被设置为高电平。该引脚只适用于硬件流控制。 |
nCTS | 清除以发送(Clear To Send), n 表示低电平有效。如果使能 CTS 流控制,发送器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。 |
SCLK | 发送器时钟输出引脚。这个引脚仅适用于同步模式。 |
2.USART配置:
- STM32在只有一个中断的情况下,仍然需要配置优先级,其作用是使能某条中断的触发通道。STM32的中断有至多两个层次,分别是抢占优先级(主优先级)和子优先级(从优先级),而整个优先级设置参数的长度为4位,因此需要首先划分抢占优先级位数和子优先级位数,通过
NVIC_PriorityGroupConfig()
实现; - 特定设备的中断优先级NVIC的属性包含在结构体NVIC_InitTypeDef中,其中字段
NVIC_IRQChannel
包含了设备的中断向量,保存在启动代码中;字段NVIC_IRQChannelPreemptionPriority
为主优先级,NVIC_IRQChannelSubPriority
为从优先级,取值的范围应根据位数划分的情况而定;最后NVIC_IRQChannelCmd
字段是是否使能,一般置为ENABLE。最后通过NVIC_Init()
来使能这一中断向量。
3.汇编实现
-
打开Keil-Project-new peoject
-
新建文件
-
芯片依旧选择STM32F103C8
- 新建main.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]
;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]
;切换成用户级线程序模式
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]
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, #'\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
;异常程序
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填充,来使当前位置与一个指定的边界对齐
EN
-
build
这里又有错误,是版本问题,修改一下就好
忘了生成.hex文件
-
McuFly
-
调试
成功 -
观察波形
debug修改相关设置
点开波形图添加寄存器
4.hel库实现
1.SRM32CubeMX
-
File-New Project,选择型号STM32F103C8,选中之后点击start project
-
System Core-RCC-High Speed Clock-Crystal/Ceramic Resonator
-
A->Z-USART1-Asynchronous
-
勾选Clock Condigiguration-PLLCLK
-
新建文件名
Project Manager- Project -Toolchain / IDE-MDK-ARM
Application Structure-Basic
-
Project Manager- Code Generator-Generated files-勾选第一个
-
Generator Code
-
Open Project
2.Keil
- 在main.c文件的while函数中添加代码
char data[]="hello windows!\n";
HAL_UART_Transmit(&huart1, (uint8_t *)data, 15, 0xffff);
HAL_Delay(1000);
- build
- McuFly
- 调试
- 分析波形
- debug
- setup
- 波形图
- debug
三、总结
这次作业我学习了解串口协议和RS-232标准,以及RS232电平与TTL电平的区别,以及USB/TTL转232的工作原理。通过后面的实验汇编语言和STM32CubeMX做两个项目,我了解了STM32CubeMX的基本操作方法,如何建立.hex文件等,比起汇编语言实现,它要方便快捷很多,了解了如何使用Keil波形图分析。当然实验过程中也遇到了很多问题,在自己查阅资料和同学的帮助下都成功地解决了。
四、参考文献
http://www.elecfans.com/emb/jiekou/20171101573461.html
https://www.sohu.com/a/168891691_669755
https://blog.csdn.net/Mark_md/article/details/108597911
https://blog.csdn.net/qq_43279579/article/details/112233696
https://blog.csdn.net/vic_to_ry/article/details/110451036
https://www.cnblogs.com/yangguang-it/p/7070787.html
- 李永忠主编.现代微机原理与接口技术:西安电子科技大学出版社,2013.10 ↩︎
本文转自 https://blog.csdn.net/zjszd/article/details/120933702,如有侵权,请联系删除。
版权声明:本文为CSDN博主「weixin_45937995」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45937995/article/details/122500944
暂无评论