STM32F103C8串口通信与流水灯操作

一、串口协议和RS-232标准,RS232电平与TTL电平的区别,"USB/TTL转232"模块的工作原理

1.串口协议

串口通信指串口按位(bit)发送和接收字节。尽管比特字节(byte)的串行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。串口通信协议是指规定了数据包的内容,内容包含了起始位、主体数据、校验位及停止位,双方需要约定一致的数据包格式才能正常收发数据的有关规范。在串口通信中,常用的协议包括RS-232、RS-422和RS-485。

2.RS-232标准

介绍
RS-232-C是美国电子工业协会EIA(Electronic Industry Association)制定的一种串行物理接口标准。RS(Recommended Standard)是英文“推荐标准”的缩写,232为标识号,C表示修改次数。RS-232-C总线标准设有25条信号线,包括一个主通道和一个辅助通道。
RS-232-C标准规定,驱动器允许有2500pF的电容负载,通信距离将受此电容限制。例如,采用150pF/m的通信电缆时,最大通信距离为15m;若每米电缆的电容量减小,通信距离可以增加。传输距离短的另一原因是RS-232属单端信号传送,存在共地噪声和不能抑制共模干扰等问题,因此一般用于20m以内的通信。

电气特性
在TxD和RxD上:
逻辑“1”:-3V~-15V
逻辑“0”:+3~+15V
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
④设置
串行通信在软件设置里需要做多项设置,最常见的设置包括波特率(Baud Rate)、奇偶校验(Parity Check)和停止位(Stop Bit)。
1)波特率(Baud Rate):
是指从一设备发到另一设备的波特率,即每秒钟多少比特bits per second (bit/s)。典型的波特率是300, 1200, 2400, 9600, 19200, 115200 等bit/s。一般通信两端设备都要设为相同的波特率,但有些设备也可以设置为自动检测波特率。
2)奇偶校验(Parity Check):
是用来验证数据正确性的。奇偶校验一般不使用,如果使用,那么既可以做奇校验(Odd Parity)也可以做偶校验(Even Parity)。
3)停止位(Stop Bit):
是在每个字节数据传输之后发送的,它用来帮助接收信号方硬件重同步。
(2)RS-485标准
①介绍
电子工业协会(EIA)于 1983 年制订并发布 RS-485 标准,并经通讯工业协会(TIA)修订后命名为 TIA/EIA-485-A,习惯地称之为 RS-485 标准。
RS-485 标准是为弥补 RS-232 通信距离短、速率低等缺点而产生的。RS-485 标准只规定了平衡发送器和接收器的电特性,而没有规定接插件、传输电缆和应用层通信协议。
RS-485 标准通常被用作为一种相对经济、具有相当高噪声抑制、相对高的传输速率、传输距离远、宽共模范围的通信平台。同时,RS-485 电路具有控制方便、成本低廉等优点。
②性能
RS-485 标准的数据信号采用差分传输方式(Differential Driver Mode),也称作平衡传输,它使用一对双绞线,将其中一线定义为 A,另一线定义为 B。
通常情况下,发送发送器 A、B 之间的正电平在+2+6V,是一个逻辑状态;负电平在-2-6V,是另一个逻辑状态。另有一个信号地 C。在 RS-485 器件中,一般还有一个“使能”控制信号。“使能”信号用于控制发送发送器与传输线的切断与连接,当“使能”端起作用时,发送发送器处于高阻状态,称作“第三态”,它是有别于逻辑“1”与“0”的第三种状态。
对于接收发送器,也作出与发送发送器相对的规定,收、发端通过平衡双绞线将 A-A与 B-B 对应相连。当在接收端 A-B 之间有大于+200mV 的电平时,输出为正逻辑电平;小于-200mV 时,输出为负逻辑电平。在接收发送器的接收平衡线上,电平范围通常在 200mV至 6V 之间。
定义逻辑 1(正逻辑电平)为 B>A 的状态,逻辑 0(负逻辑电平)为 A>B 的状态,A、B 之间的压差不小于200mV。
TIA/EIA-485 串行通讯标准的性能如下表所示:
在这里插入图片描述
RS-485 标准的最大传输距离约为 1219 米,最大传输速率为 10Mbps。
通常,RS-485 网络采用平衡双绞线作为传输媒体。平衡双绞线的长度与传输速率成反比,只有在 20kbps 速率以下,才可能使用规定最长的电缆长度。只有在很短的距离下才能获得最高速率传输。一般来说,15 米长双绞线最大传输速率仅为 1Mbps。
注意:并不是所有的 RS-485 收发器都能够支持高达 10Mbps 的通讯速率。如果采用光电隔离方式,则通讯速率一般还会受到光电隔离器件响应速度的限制。
RS-485 网络采用直线拓朴结构,需要安装 2 个终端匹配电阻,其阻值要求等于传输电缆的特性阻抗(一般取值为 120Ω)。在矩距离、或低波特率数据传输时可不需终端匹配电阻,即一般在 300 米以下、19200bps 不需终端匹配电阻。终端匹配电阻安装在 RS-485 传输网络的两个端点,并联连接在 A-B 引脚之间。

3.RS232、485电平与TTL电平的区别

通讯标准RS-232RS-485TTL
电平标准(发送端)逻辑 1:-15V ~ -3V
逻辑 0:+3V ~ +15V
逻辑 1:-6V ~ -2V
逻辑 0:+2V ~ +6V
逻辑 1:2.4V ~ 5V
逻辑 0:0 ~ 0.5V
传输方式采用不平衡传输方式,即所谓单端通讯采用平衡传输,即差分传输方式(使用两根线的电压差表示数据)计算机处理器控制的设备内部各部分之间通信的标准技术
传输距离适合本地设备之间的通信,传输距离一般不超过20m传输距离为几十米到上千米
传输速度传输速率较低,最高波特率为19200bps数据最高传输速率为10Mbps

4."USB/TTL转232"模块的工作原理(以CH340芯片为例)

CH340G_VCC:模块供电点
VCC+5V:从USB取出来的5V电源
VCC+3V3:模块稳压出来的3V3电源(3.0V-3.6V)
(短路VCC+5V到CH340G_VCC:CH340G供电为5V,TTL电平为5V)
(短路VCC+3V3到CH340G_VCC:CH340G供电为3V3,TTL电平为3V3)
CH340G_TXD:串行数据输出
CH340G_RXD:串行数据输入
GND:模块接地(与目标系统地相连)

二、用HAL库点亮流水灯

1.安装STM32CUBEMX

(官网下载需要绑定邮箱或者注册)
(1)管理员身份运行安装程序,点击next:
在这里插入图片描述

(2)点击"I accept the terms of this license agreement",接着选择Next:
在这里插入图片描述

(3)勾选第一个即可,第二个选项是是否同意ST公司收集你的个人使用信息等:
在这里插入图片描述
(4)选择安装位置,默认位置是安装在C盘中(注意:安装位置不要出现中文):
在这里插入图片描述
(5)直接点yes
在这里插入图片描述

(6)直接点NEXT,其他不用设置 之后开始安装。
(7)安装完成,点Done退出:
在这里插入图片描述

2.安装HAL库

(1)打开安装好的STMCubeMX
在这里插入图片描述
(2)点击HELP->Manage embedded software packages :
(3)会跳出来一个选择型号界面 勾选上你要安装的HAL库, 点击“Install Now” 直到安装成功。 如下图:(如果出现错误重新启动软件)
在这里插入图片描述

3.新建项目

(1)回到STMCubeMX的主界面,创建新项目:
在这里插入图片描述
(2)在part name里选择自己的芯片,点击信息栏中的具体芯片信息选中,点击start project:
在这里插入图片描述
(3)点击system core,进入SYS,在debug下选择serial wire:
在这里插入图片描述
(4)配置时钟,进入上面的rcc,有两个时钟,一个是hse和lse,我们要用是GPIO接口,而这些接口都在APB2里:
接下来观察时钟架构,APB2总线的时钟由hse控制,同时在这个界面得把PLLCLK右边选上:
在这里插入图片描述
(5)将hse那里设为Crystal/Ceramic Resonator:
在这里插入图片描述
(6)接下来就是点击相应的引脚设置输出寄存器了,就是output那一项,一共选了三个,是PA4,PB9,PC15:
在这里插入图片描述
把这三个全部设置为高电平:
在这里插入图片描述
(7)点击project manager,配置好自己的路径和项目名,然后IDE那项改为MDK-ARM:
在这里插入图片描述
(8)进入 code generate,选择生成初始化.c/.h文件,然后点击generate code,选择open project,然后就到KEIL5了:
在这里插入图片描述

4.keil仿真调试

(1)在自动跳转到keil5后,打开main.c文件,滑倒主函数那一部分:
在这里插入图片描述
(2)将下面代码放入主函数中(替代里面的内容)

SystemClock_Config();//系统时钟初始化
  MX_GPIO_Init();//gpio初始化
  while (1)
  {		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);//PA4亮灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);//PC15熄灯
		HAL_Delay(1000);//延时1s
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9亮灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);//PC15熄灯
		HAL_Delay(1000);//延时1s		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);//PC15亮灯
		HAL_Delay(1000);//延时1s
	}

5.电路连接

GNDGND
3V33V3
RXDA9
TXDA10
B9
绿C15
A4
  • 程序烧录
    串口烧录要断电之后把boot0置0才能正常运行
    在这里插入图片描述

6.观察GPIO端口的输出波形

(1)Target界面中,选择跟正确的晶振大小,我使用的是8MHz的外部晶振。这个选项在软件仿真中起到很重要的作用,如果选择错误,那么波形一定是错误的,因为时间不准确
在这里插入图片描述
(2)Debug页的设置:
在这里插入图片描述
(3)点击Debug,进入调试界面:
在这里插入图片描述
(4)选择逻辑分析仪:
在这里插入图片描述
(5)选择要观察的引脚:
点击Setup Logic Analyzer,然后点击右上角添加引脚(需要手打),选中引脚一个个设置,点击close。
在这里插入图片描述
(6)点击In/Out将Grid的大小调为1s,勾选Signal info和Cursor能设置显示起始线并能看到相关信息
在这里插入图片描述
(7)点击Run即可开始运行
在这里插入图片描述
(8)点击stop,由波形图可知,引脚为低电平的灯亮,高电平的灯不亮,高低电平转换周期(LED闪烁周期)为0.982511s,约为1s。
在这里插入图片描述

三、用HAL库输出hello world!

1.新建项目

(1)回到STMCubeMX的主界面,创建新项目:
在这里插入图片描述
(2)在part name里选择自己的芯片,点击信息栏中的具体芯片信息选中,点击start project:
在这里插入图片描述
(3)点击system core,进入SYS,在debug下选择serial wire:
在这里插入图片描述
(4)配置时钟,进入上面的rcc,有两个时钟,一个是hse和lse,我们要用是GPIO接口,而这些接口都在APB2里:
接下来观察时钟架构,APB2总线的时钟由hse控制,同时在这个界面得把PLLCLK右边选上:
在这里插入图片描述
(5)设置USART1
在这里插入图片描述
(7)点击project manager,配置好自己的路径和项目名,然后IDE那项改为MDK-ARM:
在这里插入图片描述
(8)进入 code generate,选择生成初始化.c/.h文件,然后点击generate code,选择open project,然后就到KEIL5了:
在这里插入图片描述

2.keil仿真调试

(1)在main.c中的while循环中添加代码:

char data[]="hello world!\n";
	HAL_UART_Transmit(&huart1, (uint8_t *)data, 15, 0xffff);
	HAL_Delay(1000);

3.电路连接

连接方式与流水灯相同。

4.程序烧录

程序烧录设置与流水灯相同。

5.串口调试

BOOT0置0,BOOT1置1,打开野火多功能调试助手,可以看到接收成功。
在这里插入图片描述

6.观察波形

(1)Target界面中,选择跟正确的晶振大小,我使用的是8MHz的外部晶振。这个选项在软件仿真中起到很重要的作用,如果选择错误,那么波形一定是错误的,因为时间不准确
在这里插入图片描述
(2)Debug页的设置:
在这里插入图片描述
(3)点击Debug,进入调试界面:
在这里插入图片描述
(4)选择逻辑分析仪:
在这里插入图片描述
(5)编译,debug,添加要观察的引脚:
在这里插入图片描述
(6)观察波形。
在这里插入图片描述

四、用寄存器方式实现点亮流水灯

1.创建项目

(1)打开Keil5,点击Project,选择第一项新建工程,并设置好工程名和路径,不要有中文

在这里插入图片描述
(2)设置工程的目标环境,即选择芯片STM32F103C8,然后点击OK
在这里插入图片描述
(3)点击OK之后弹出来的页面不用选择什么,直接叉掉
在这里插入图片描述

(4)点击“Add New Item to Group ‘Source Group1’”,添加一个.c文件,并设置好名称,我这里设置的是main,然后选择路径,设置完成后点击Add
在这里插入图片描述
选择文件类型,取名为main。
在这里插入图片描述
(5)在电脑中找到starup_stm32f10x_md.s文件,并将其复制到新建的项目下
在这里插入图片描述
在这里插入图片描述
(6)右击Source Group1,选择“Add Existing Files to Group ‘Source Group1’”,将文件类型选择为All Files,选择刚刚复制添加的启动文件,然后点击Add,最后点击Close
在这里插入图片描述
在这里插入图片描述
(7)点击魔术棒→Output→勾选Create HEX File→OK
在这里插入图片描述

2.编写程序

(1)在main.c中写入如下代码:

#define GPIOB_BASE 0x40010C00
#define GPIOC_BASE 0x40011000
#define GPIOA_BASE 0x40010800

#define RCC_APB2ENR (*(unsigned int *)0x40021018)

#define GPIOB_CRH (*(unsigned int *)0x40010C04)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_CRL (*(unsigned int *)0x40010800)

#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)
	


void SystemInit(void);
void Delay_ms(volatile  unsigned  int);
void A_LED_LIGHT(void);
void B_LED_LIGHT(void);
void C_LED_LIGHT(void);
void Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<800;i++);
}

void A_LED_LIGHT(){
	GPIOA_ODR=0x0<<4;		//PA4低电平
	GPIOB_ODR=0x1<<9;		//PB9高电平
	GPIOC_ODR=0x1<<15;		//PC15高电平
}
void B_LED_LIGHT(){
	GPIOA_ODR=0x1<<4;		//PA4高电平
	GPIOB_ODR=0x0<<9;		//PB9低电平
	GPIOC_ODR=0x1<<15;		//PC15高电平
}
void C_LED_LIGHT(){
	GPIOA_ODR=0x1<<4;		//PA4高电平
	GPIOB_ODR=0x1<<9;		//PB9高电平
	GPIOC_ODR=0x0<<15;		//PC15低电平	
}

int main(){
	int j=100;
	// 开启时钟
	RCC_APB2ENR |= (1<<3); // 开启 GPIOB 时钟
	RCC_APB2ENR |= (1<<4); // 开启 GPIOC 时钟
	RCC_APB2ENR |= (1<<2); // 开启 GPIOA 时钟
	
	
	// 设置 GPIO 为推挽输出
	GPIOB_CRH&= 0xffffff0f;	//设置位 清零		
	GPIOB_CRH|=0x00000020;  //PB9推挽输出

	GPIOC_CRH &= 0x0fffffff; //设置位 清零		
	GPIOC_CRH|=0x30000000;  //PC15推挽输出


	GPIOA_CRL &= 0xfff0ffff; //设置位 清零		
	GPIOA_CRL|=0x00010000; //PA4推挽输出

	// 3个LED初始化为不亮(即高点位)
	GPIOB_ODR |= (1<<9); 
	GPIOC_ODR |= (1<<15); 
	GPIOA_ODR |= (1<<4);  
	
	while(j){
		
		B_LED_LIGHT();
		Delay_ms(1000000);

		C_LED_LIGHT();
		Delay_ms(1000000);

		A_LED_LIGHT();
		Delay_ms(1000000);
	}
	
}


void SystemInit(){
	
}

(2)编译程序并创建hex文件
在这里插入图片描述
在这里插入图片描述

3.连接电路

电路连接与使用HAL库点亮流水灯完全一样

4.烧录运行

串口烧录跟使用HAL库一样要断电之后置BOOT0为0,BOOT1为1
在这里插入图片描述

芯片写入成功。
在这里插入图片描述

5.观察实验结果

petal_20221013_150637

6.观察输出波形

(1)相关设置与使用HAL方式完全一样
(2)点击Run开始运行,运行一段时间后点击Stop停止运行并观察LED闪烁周期
在这里插入图片描述

五、寄存器实现helloworld

寄存器实现过程大致与流水灯相同,只有有以下需要修改:

1.程序编写

在文件夹下新建hello.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

编译过后程序烧录

2.烧录运行

串口烧录跟使用HAL库一样要断电之后置BOOT0为0,BOOT1为1
在这里插入图片描述

芯片写入成功。
在这里插入图片描述

3.观察波形

(1)Target界面中,选择跟正确的晶振大小,我使用的是8MHz的外部晶振。这个选项在软件仿真中起到很重要的作用,如果选择错误,那么波形一定是错误的,因为时间不准确
在这里插入图片描述
(2)Debug页的设置:
在这里插入图片描述
(3)点击Debug,进入调试界面:
在这里插入图片描述
(4)选择逻辑分析仪:
在这里插入图片描述
(5)编译,debug,添加要观察的引脚:
在这里插入图片描述
(6)观察波形。

六、总结

安装软件及实验过程中需要设置的参数比较多,同时安装软件比较多,需要静下心来,多试几次。在用两种不同方式点亮流水灯的过程中可以发现STM32CubeMX中使用HAL库点亮流水灯的方式比使用寄存器点亮流水灯的方式要容易一些。

七、参考链接

参考链接
参考连接
串口参考链接

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值