一、实验要求
(一) 了解串口协议和RS-232标准,以及RS232电平与TTL电平的区别;了解"USB/TTL转232"模块(以CH340芯片模块为例)的工作原理。
(二)安装 stm32CubeMX,配合Keil,使用寄存器方式(汇编或C,不限) 或HAL库这两种方式,完成下列任务:
1、重做上一个LED流水灯作业,即用GPIO端口完成3只LED红绿灯的周期闪烁。 2、完成一个STM32的USART串口通讯程序(查询方式即可,暂不要求采用中断方式),要求: 1)设置波特率为115200,1位停止位,无校验位; 2)STM32系统给上位机(win10)连续发送“hello windows!”。win10采用“串口助手”工具接收。
(三)在没有示波器条件下,可以使用Keil的软件仿真逻辑分析仪功能观察管脚的时序波形,更方便动态跟踪调试和定位代码故障点。 请用此功能观察第1题中3个GPIO端口的输出波形,和第2题中串口输出波形,并分析其波形反映的时序状态正确与否,高低电平转换周期(LED闪烁周期)实际为多少。
二、实验过程及结果
(一)任务一
1.串口协议
串口通信是指串口按位(bit)发送和接收字节。尽管比特字节(byte)的串行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。串口通信协议是指规定了数据包的内容,内容包含了起始位、主体数据、校验位及停止位,双方需要约定一致的数据包格式才能正常收发数据的有关规范。在串口通信中,常用的协议包括RS-232、RS-422和RS-485。
通信方式: 一般情况下,设备之间的通信方式分为串行通信和并行通信。
串行通信分类:
按照数据的传输方向分为: ① 单工:数据传输只支持数据在一个方向上传输。 ② 半双工:允许数据在两个方向上传输。但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;它不需要独立的接收端和发送端,两者可以合并一起使用一个端口。 ③ 全双工:允许数据同时在两个方向上传输。因此,全双工通信是两个单工通信方式的结合,需要独立的接收端和发送端。
按照通信方式分为: ① 同步通信:带时钟同步信号传输。比如:SPI,IIC通信接口。 ② 异步通信:不带时钟同步信号。比如:UART(通用异步收发器),单总线。
常见串口通信的接口:
串口通讯 (Serial Communication)是一种设备间非常常用的串行通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。 对于通讯协议,以分层的方式来理解,最基本的是把它分为物理层和协议层。物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。
1)物理层
串口通讯的物理层有很多标准及变种,RS-232 标准主要规定了信号的用途、通讯接口以及信号的电平标准。 使用 RS-232 标准的串口设备间常见的通讯结构如下图所示:
两个通讯设备的“ DB9 接口”之间通过串口信号线建立起连接,串口信号线中使用“RS-232 标准”传输数据信号。由于 RS-232 电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的 “TTL 标准”的电平信号,才能实现通讯。RS232标准串口主要用于工业设备直接通信,电平转换芯片一般有MAX3232,SP3232。 ① 电平标准 根据通讯使用的电平标准不同,串口通讯可分为 TTL标准及 RS-232标准。
常见的电子电路中常使用 TTL 的电平标准,理想状态下,使用 5V 表示二进制逻辑 1 ,使用 0V 表示逻辑 0 ;而为了增加串口通讯的远距离传输及抗干扰能力,它使用 -15V 表示逻辑 1 ,+15V 表示逻辑 0 。 使用 RS232 与 TTL 电平校准表示同一个信号时的对比如下图所示:
因为控制器一般使用 TTL 电平标准,所以常常会使用 MA3232 芯片对 TTL 及 RS-232电平的信号进行互相转换。 ② RS-232 信号线 在最初的应用中,RS-232 串口标准常用于计算机、路由与调制调解器(MODEN,俗称“猫”)之间的通讯 ,在这种通讯系统中,设备被分为数据终端设备 DTE(计算机、路由)和数据通讯设备 DCE(调制调解器)。我们以这种通讯模型讲解它们的信号线连接方式及各个信号线的作用。 在旧式的台式计算机中一般会有 RS-232 标准的 COM 口(也称 DB9 接口)。
其中接线口以针式引出信号线的称为公头,以孔式引出信号线的称为母头。在计算机中一般引出公头接口,而在调制调解器设备中引出的一般为母头,使用串口线即可把它与计算机连接起来。通讯时,串口线中传输的信号就是使用前面讲解的 RS-232 标准调制的。 在这种应用场合下,DB9 接口中的公头及母头的各个引脚的标准信号线接法如下图所示:
信号线说明 ( 公头,为方便理解,可把 DTE 理解为计算机, DCE 理解为调制调解器) 上表中的是计算机端的 DB9 公头标准接法,由于两个通讯设备之间的收发信号(RXD与 TXD)应交叉相连,所以,调制调解器端的 DB9 母头的收发信号接法一般与公头的相反,两个设备之间连接时,只要使用“直通型”的串口线连接起来即可。
串口线中的 RTS、CTS、DSR、DTR 及 DCD 信号,使用逻辑 1 表示信号有效,逻辑 0表示信号无效。例如,当计算机端控制 DTR 信号线表示为逻辑 1 时,它是为了告知远端的调制调解器,本机已准备好接收数据,0 则表示还没准备就绪。 在目前的其它工业控制使用的串口通讯中,一般只使用 RXD、TXD 以及 GND 三条信号线,直接传输数据信号,而 RTS、CTS、DSR、DTR 及 DCD 信号都被裁剪掉了。
2)协议层
串口通讯的数据包由发送设备通过自身的 TXD 接口传输到接收设备的 RXD 接口。在串口通讯的协议层中,规定了数据包的内容,它由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据。
① 波特率 串口异步通讯中由于没有时钟信号(如 DB9接口中是没有时钟信号的),所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码,上图中用虚线分开的每一格就是代表一个码元。常见的波特率为4800、9600、115200 等。 ② 通讯的起始和停止信号 串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑0的数据位表示,而数据包的停止信号可由0.5、1、1.5或2个逻辑1的数据位表示,只要双方约定一致即可。 ③ 有效数据 在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度常被约定为 5、6、7 或 8 位长。 ④ 数据校验 在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0 校验(space)、1 校验(mark)以及无校验(noparity)。 奇校验要求有效数据和校验位中“1”的个数为奇数,比如一个 8 位长的有效数据为: 01101001,此时总共有 4 个“1”,为达到奇校验效果,校验位为“1”,最后传输的数据将是 8 位的有效数据加上 1 位的校验位总共 9 位。 偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数,比如数据 帧:11001010,此时数据帧“1”的个数为 4 个,所以偶校验位为“0”。 0 校验是不管有效数据中的内容是什么,校验位总为“0”,1 校验是校验位总为“1”。
2.USB/TTL转232
1)USB/TTL/232串口
① USB,通过USB电平工作。
USB电平: 电源线是5V,为USB设备提供最大500mA的电流,它与数据线上的电平无关,数据线是差分信号,通常D+和D-在+400mV~-400mV间变化,除去屏蔽层,有4根线,分别是VCC、GND和D+、D-两根信号线。 5V是USB的电源电压,给USB device供电用的。 信号线对于2.0,D+比D-大200mV时为1,D-比D+大200mV时为0。
② 232串口,通过232电平标准工作。
232电平,负逻辑: 逻辑1(MARK)=-3V~-15V;逻辑0(SPACE)=+3~+15V。 将串口和单片机进行通信,只需要2 脚 RXD、3 脚 TXD 和 5 脚 GND 即可,其名字和单片机上的串口名一样,但是不能直接和单片机对连通信。
③ 单片机串口是TTL电平,所以叫TTL串口或UART 串口。
TTL电平: +5V等价于逻辑“1”,0V等价于逻辑“0”(采用二进制来表示数据时)。 PC机上的通信接口有USB接口,相应电平逻辑遵照USB原则;有DB9接口(九针口),相应电平逻辑遵照RS-232原则。 单片机上的串行通信通过单片机的RXD、TXD、VCC、GND四个引脚,相应电平逻辑遵照TTL原则。
2)USB/TTL转232
常用的常用232串口转TTL有MAX232、MAX3232、SP232、SP3232等。 常用的USB转TTL串口芯片有CH340、CP2102、PL2303、FT232等。 MAX232等芯片是将TTL转换为RS232信号或者将RS232信号转换为TTL。 CH340、PL2303等芯片是直接将USB信号转换为TTL电平或者TTL电平转换为USB信号。
① USB转232串口
原理:USB接口>>>PL2303或CH340>>>MAX232>>>9针接口 信号分析:电脑USB接口>>>电脑输出USB电平信号>>>PL2303或CH340>>>TTL电平>>>MAX232芯片>>>电脑串口接口
② TTL转232串口
3)USB转串口CH340接线
USB转串口模块可以使用5V电压供电,需要将跳帽按下图安装。 USB转串口模块可以使用3.3V电压供电,需要将跳帽按下图安装。 可以对USB转串口模块进行测试,将USB的电压引脚用跳帽接上,然后将RXD和TXD两个引脚用跳帽或者杜邦线接上。 然后打开串口终端,点击“手动发送”或者“自动发送”,如果在接收区可以接收到数据,说明USB转串口模块工作正常,否则需要检查接线是否正确、电路板元器件是否损坏。
(二)任务二
1.安装stm32CubeMX
下载链接: https://www.st.com/en/development-tools/stm32cubemx.html#get-software 选择help中的manage embedded software packages,找到相应的stm32,点击install now进行下载。
2.LED流水灯
1)寄存器方式
https://blog.csdn.net/weixin_45919652/article/details/120746247
2)HAL库方式
① 工程创建 选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR 。
在Part Number输入名称查找,选中芯片,点击右上角的Start Project进入界面。
点击System Core中的SYS,在Debug处选择Serial Wire。
左侧为MCU外设资源选择: Categories 种类选择,将MCU各种外设和资源分类,供用户选择使用。 A-Z顺序选择,MCU的外设资源按A-Z排序,供用户选择使用。
中间为外设配置: 可以选择外设的各种功能,选择串口模式(异步、同步、半双工)串口接收终端,和串口DMA传输等。
右侧为预览界面: 分为引脚预览和系统预览 引脚预览可以查看引脚配置了什么功能,和各个引脚的位置,任意点击一个引脚即可设置该引脚的各种功能。 淡黄色表示不可配置引脚,电源专用引脚以黄色突出显示,其配置不能更改。 深黄色表示配置了一个I/O口的功能,但是没有初始化对应外设功能,引脚处于no mode状态。 绿色表示配置成功。
选择Clock Configuration,将PLLCLK右边选上。
返回 Pinout & Configuration,选择RCC,将HSE修改为Crystal/Ceramic Resonator。
点击管脚,选择PA1,PA3,PA5,选择为GPIO_Output。
点击Project Manager,选择路径和输入项目名,然后IDE改为MDK-ARM,点击右上角的GENERATE CODE。
② 添加代码 进入设定的工程目标目录,打开MDK-ARM文件夹,通过keil打开项目,点击main.c,找到主函数main中的while循环。
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);
HAL_Delay(1000);
延时函数(HAL_Delay) 函数原型: void HAL_Delay (__IO uint32_t Delay) 参数说明:Delay表示所要延时的时间大小,单位是毫秒 写管脚函数(HAL_GPIO_WritePin) 函数原型: void HAL_GPIO_WritePin (GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,GPIO_PinState PinState) 参数说明: GPIOx: 管脚组(x的取值为A~G) GPIO_Pin: 管脚编号(x的取值为0~15) PinState: 管脚的状态(取值为GPIO_BIT_RESET表示0, GPIO_BIT_SET表示1)
点击魔法棒 ,在Output 中勾选 Create HEX File 生成 hex 文件,在Debug中选择Use Simulator ,设置Dialog DLL项为DARMSTM.DLL ,parameter项为-pSTM32F103C8 。
③ 硬件连接 使用USB-TTL直接进行串口下载,将USB-TTL的GND和3.3V接入STM32最新系统板的GND和3.3V,然后TXD和RXD分别接入A10和A9引脚。
接入后按照程序中GPIOx的引脚接上LED灯,将LED灯+极接入3.3V的电压,且最小核心板要利用跳线帽实现boot0置1,boot1置0。
打开 mcuisp 软件,开始烧录。
④ 实际效果
3.STM32的USART串口通讯
通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个UART(Universal Asynchronous Receiver and Transmitter),是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。 串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数据信息、停止信息,可能还有校验信息。USART 就是对这些传输参数有具体规定,当然也不是只有唯一一个参数值,很多参数值都可以自定义设置,只是增强它的兼容性。
1)HAL库方式
① 工程创建 选择STM32F103C8开发板,点击右上角的Start Project进入界面。
配置时钟,点击HSE,选择Crystal/Ceramic Resonator。
设置USART2,点击Mode,选择Asynchronous。
点击Clock Configuration选择HSE和PLLCLK。
设置中断,在NVIC Settings中点击Enabled。
设置项目名称和路径,修改Application Structure为Basic,Toolchain/IDE为MDK-ARM,在Code Generator中勾选,生成项目。
② 添加代码 进入设定的工程目标目录,打开MDK-ARM文件夹,通过keil打开项目,点击main.c,找到主函数main中的while循环。
char data[]="hello windows!\n";
HAL_UART_Transmit(&huart2, (uint8_t *)data, 15, 0xffff);
HAL_Delay(1000);
点击魔法棒 ,在Output 中勾选 Create HEX File 生成 hex 文件,在Debug中选择“Use Simulator ”,设置Dialog DLL项为DARMSTM.DLL ,parameter项为-pSTM32F103C8 。
③ 操作步骤 使用USB-TTL直接进行串口下载,将USB-TTL的GND和3.3V接入STM32最新系统板的GND和3.3V,然后TXD和RXD分别接入A10和A9引脚。
BOOT0置1,BOOT1置0,打开mcuisp,选择文件路径,开始烧录。
BOOT0置0,打开野火多功能调试助手。
2)寄存器方式
① 源码
;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, #'\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
② 操作步骤 新建工程,不用勾选 CORE 和 Startup ,具体参考基于MDK创建纯汇编语言的STM32工程。
点击魔法棒 ,在Output 中勾选 Create HEX File 生成 hex 文件,在Debug中选择“Use Simulator ”,设置Dialog DLL项为DARMSTM.DLL ,parameter项为-pSTM32F103C8 。
使用USB-TTL直接进行串口下载,将USB-TTL的GND和3.3V接入STM32最新系统板的GND和3.3V,然后TXD和RXD分别接入A10和A9引脚。
其余步骤与HAL库实现STM32的USART串口通讯时相同。
(三)任务三
1.波形分析:LED流水灯
1)寄存器方式
https://blog.csdn.net/weixin_45919652/article/details/120746247
2)HAL库方式
打开逻辑分析仪:
添加要观察的管脚PA1、PA3和PA5,修改各个管脚的显示方式,将Display Type处设置为Bit 。
查询可输入的端口: ① 在左下角Command窗口输入dir vtreg 命令,查看有哪些引脚可以被检测。 ② 直接输入PORTA. ,PORTB. ,回车,目标端口显示出来。 ③ 直接以PORTX >> X 的形式输入,内容取决于代码中定义的管脚。
点击Run(F5) ,执行一段时间后,点击Stop 。 观察波形: ① 3个管脚的电平从0 1 1->1 0 1->1 1 0->0 1 1不断循环变化,且连接管脚的灯在低电平时亮。 ② 每次变化的时间大约为1.01s,与定义的1000ms(1s)相近。
2.波形分析:STM32的USART串口通讯
1)HAL库方式
打开Serial Windows中的UART #2 窗口和逻辑分析仪,添加要观察的端口,修改各个显示方式,将Display Type处设置为Bit 。
观察波形:每隔一段时间(大约1s)电平位发生变化,程序周期性输出,UART #2 窗口循环显示hello windows! 。
2)寄存器方式
打开Serial Windows中的UART #1 窗口和逻辑分析仪,添加要观察的端口,修改各个显示方式,将Display Type处设置为Bit 。
观察波形:每隔一段时间(大约1s)电平位发生变化,程序周期性输出,UART #1 窗口循环显示hello windows 。
三、实验总结
在本次串口通信的实验过程中,我发现,较使用寄存器方式而言,使用HAL库完成LED流水灯和STM32的USART串口通讯会更加方便和高效,因为它无需自己编写代码来配置管脚。同时,利用keil的逻辑分析仪来观察相应引脚的波形,更加直观地让我认识到程序的运行过程,加深了我对如何实现LED流水灯和STM32的USART串口通讯的理解。
四、参考资料
1、串口通信 2、KEIL5仿真——示波器显示 3、USB转串口CH340接线方法 4、STM32实现LED闪烁——基于HAL库 5、STM32最小核心板F103串口通信USART 6、搭建STM32开发环境——STM32CubeMX,Keil5 7、USB转TTL串口、USB转232串口、232串口转TTL串口 8、利用KEIL的软件仿真的逻辑分析仪功能观察GPIO的波形 9、基于 MDK 创建 STM32 汇编程序:串口输出 Hello world
|