STM32F103xx 的USART1 移植到STM32F105RBT6

news/2024/11/9 3:35:23/

1. STM32F103 和 STM32F105 的时钟配置区别,STM32F105 默认使用的外部晶振是25Mhz,需要改成8Mhz

stm32f10x.h

#if !defined  HSE_VALUE#ifdef STM32F10X_CL#define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */#else #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */#endif /* STM32F10X_CL */
#endif /* HSE_VALUE */

在这里插入图片描述

system_stm32f10x.c

#ifdef STM32F10X_CL/* Configure PLLs ------------------------------------------------------*//* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz *//* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV2 | RCC_CFGR2_PLL2MUL10 |RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);/* Enable PLL2 */RCC->CR |= RCC_CR_PLL2ON;/* Wait till PLL2 is ready */while((RCC->CR & RCC_CR_PLL2RDY) == 0){}/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9); 
#else    /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |RCC_CFGR_PLLMULL));RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */

在这里插入图片描述

2. 在keil里面修改宏定义,每个宏之间用逗号隔开, STM32F10X_CL 宏也可以不定义,因为在芯片选STM32F105RBT6 就默认定义了这个宏

在这里插入图片描述

3. 测试时钟配置是否OK

RCC_ClocksTypeDef get_rcc_clock;
RCC_GetClocksFreq(&get_rcc_clock);

在这里插入图片描述

4. printf 重定向, 重定向后printf 就会往串口里面打日志了,然后就可以用串口工具SSCOM看日志了

USART1.c

#if 1
#pragma import(__use_no_semihosting)             
//±ê×¼¿âÐèÒªµÄÖ§³Öº¯Êý                 
struct __FILE 
{ int handle; }; FILE __stdout;       
//¶¨Òå_sys_exit()ÒÔ±ÜÃâʹÓðëÖ÷»úģʽ    void _sys_exit(int x) 
{ x = x; 
} 
//Öض¨Òåfputcº¯Êý 
//Öض¨Òåfputcº¯Êý 
int fputc(int ch, FILE *f)
{      while((USART1->SR&0X40)==0);//Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï   USART1->DR = (u8) ch;      return ch;
}
#endif

5. 串口打印的日志全是乱码的话,如果时钟配置OK的话就把波特率降一点,因为我的板子在串口TX,RX线上分别接了一个光耦,所以波特率不能用太高,115200 的话就会乱码,光耦反应不过来,用9600 的波特率就好了

TX 接一个光耦的情况下,由于光耦内部存在电容和滞后现象,信号不能瞬间传导,因此在高速传输时,会出现上升沿或下降沿不够陡峭、波形失真、误码率过高等问题,从而影响通信质量和可靠性。因此,在此种情况下,建议降低串口通信的波特率,以确保通信质量和稳定性。具体的波特率取值视情况而定,一般可以通过实验来确定合适的波特率。

int main(void)
{RCC_ClocksTypeDef get_rcc_clock;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);			//ÉèÖÃÖжϷÖ×édelay_init();			//ÑÓʱº¯Êý³õʼ»¯ST_USART1_Init(9600);		//³õʼ»¯USART1RCC_GetClocksFreq(&get_rcc_clock);while(1){printf("123\r\n");delay_ms(500);}
}

在这里插入图片描述

6. 打开串口工具,原来用115200 波特率是乱码的,换9600 就好了,看自己板子吧,

在这里插入图片描述

7. 串口初始化

ST_USART1.c

#include "sys.h"
#include "ST_USART1.h"//¼ÓÈëÒÔÏ´úÂë,Ö§³Öprintfº¯Êý,¶ø²»ÐèҪѡÔñuse MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//±ê×¼¿âÐèÒªµÄÖ§³Öº¯Êý                 
struct __FILE 
{ int handle; }; FILE __stdout;       
//¶¨Òå_sys_exit()ÒÔ±ÜÃâʹÓðëÖ÷»úģʽ    void _sys_exit(int x) 
{ x = x; 
} 
//Öض¨Òåfputcº¯Êý 
//Öض¨Òåfputcº¯Êý 
int fputc(int ch, FILE *f)
{      while((USART1->SR&0X40)==0);//Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï   USART1->DR = (u8) ch;      return ch;
}
#endif #if EN_USART1_RX  //Èç¹û¶¨ÒåÁËʹÄܽÓÊÕu8 USART1_RX_BUF[USART1_REC_MAX_LEN];//½ÓÊÕ»º´æ£¬×î´óUSART_REC_MAX_LENu16 USART1_RX_STA=0;//½ÓÊÕ״̬±ê¼Ç
//½ÓÊÕ״̬
//bit15£¬	½ÓÊÕÍê³É±êÖ¾
//bit14£¬	½ÓÊÕµ½0x0d
//bit13~0£¬	½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿/*
Copyright:
@file: ST_USART1.C
@Version: V0.0.1
@Author: dragon   
@Date: 2020/06/14
@Description: USART1 Init
@Param:  bound:´®¿Ú²¨ÌØÂÊ
@Retval: None
@Note: None
*/
void ST_USART1_Init(u32 bound){GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);//ʹÄÜUSART1,GPIOAʱÖÓUSART_DeInit(USART1);//GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA,&GPIO_InitStructure);//GPIOA.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA.10  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	NVIC_Init(&NVIC_InitStructure);	USART_InitStructure.USART_BaudRate = bound;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);USART_Cmd(USART1, ENABLE); 
}void USART1_IRQHandler(void)                	{u8 Res;#if SYSTEM_SUPPORT_OS OSIntEnter();    #endifif(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){Res =USART_ReceiveData(USART1);	if((USART1_RX_STA&0x8000)==0){if(USART1_RX_STA&0x4000){if(Res!=0x0a)USART1_RX_STA=0;else USART1_RX_STA|=0x8000;}else {	if(Res==0x0d)USART1_RX_STA|=0x4000;else{USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ;USART1_RX_STA++;if(USART1_RX_STA>(USART1_REC_MAX_LEN-1)){USART1_RX_STA=0;printf("USART1 over max length!\n");}}}}   		 } #if SYSTEM_SUPPORT_OSOSIntExit();  											 #endif}void ST_Usart1_Receive_Data(){u16 len=0;u16 t;if(USART1_RX_STA&0x8000){					   len=USART1_RX_STA&0x3fff;printf("\r\nUSART1 Received data is:\r\n\r\n");for(t=0;t<len;t++){USART_SendData(USART1, USART1_RX_BUF[t]);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);}printf("\r\n\r\n");USART1_RX_STA=0;}}
#endif

ST_USART1.h

#ifndef __ST_USART1_H
#define __ST_USART1_H
#include "sys.h"
#include "stdio.h"#define USART1_REC_MAX_LEN 128//¶¨Òå×î´ó½ÓÊÕ×Ö½Ú128
#define EN_USART1_RX 1 //ʹÄÜ£¨1£©/½ûÖ¹£¨0£©´®¿Ú1½ÓÊÕextern u8 USART1_RX_BUF[USART1_REC_MAX_LEN];//½ÓÊÕ»º´æ£¬×î´óUSART_REC_MAX_LEN¸ö×Ö½Ú£¬Ä©×Ö½ÚΪ»»Ðзû
extern u16 USART1_RX_STA;//½ÓÊÕ״̬±êÖ¾void ST_USART1_Init(u32 bound);
void ST_Usart1_Receive_Data(void);
#endif
```

http://www.ppmy.cn/news/238544.html

相关文章

hacknet攻略(更新中)

序章 然后点自己的电脑&#xff0c;再点一下SCAN(扫描可用主机)&#xff0c;再点断开 然后点蓝色的电脑&#xff0c;是连接的意思 点中间Probe系统图标&#xff0c;看开放端口数 若端口数为0可以使用porthakc命令直接黑入系统 几个会用到的命令cd, rm * ,dc关闭连接&…

工作上常用的sql写法/函数

保留两位小数 10 &#xff1a;十进制 2&#xff1a;两位小数 100&#xff1a;除数 convert(taar.f_score/100,decimal(10,2)) 日期转换 FROM_UNIXTIME(f_submit_time/1000, %Y-%m-%d %T); UNIX_TIMESTAMP(NOW()) * 1000; FROM_UNIXTIME(UNIX_TIMESTAMP(NOW()) * 1000/1000, …

CDN如何帮助我们的网站实现安全?

各类网络攻击正在变得越来越复杂&#xff0c;它们有可能导致服务可用性的严重中断和企业的财务损失。根据Gartner的数据&#xff0c;IT行业平均停机每分钟就将为企业带来超过3万元的损失。 对于每个具有在线相关业务的企业&#xff0c;如何能以安全、可靠和快速的方式服务于用…

柯尼卡/KonicaFTP扫描设置

1、在扫描一体机上问网络IP地址&#xff0c;新注册FTP. 2、在通讯簿FTP输入对应的IP、用户ID.密码.点确定。 3、在需要扫描的电脑上安装对应驱动扫描程序&#xff0c;设置对应文件夹。

大数据存储与处理技术探索:Hadoop HDFS与Amazon S3的无尽可能性【上进小菜猪大数据】

上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。 大数据时代带来了数据规模的爆炸性增长&#xff0c;对于高效存储和处理海量数据的需求也日益迫切。本文将探索两种重要的大数据存储与处理技术&#xff1a;Hadoop HDFS和Amazon S3…

【PyQt5】(01)PyQt的详细介绍

文章目录 前言一、PyQt的前世今生1.1 PyQt6、PyQt5和PyQt41.2 商业版和开源版1.3 支持的操作系统 二、 PyQt的优点三、PyQt的应用场景总结 前言 PyQt是使用Python语言编写的QT库的界面工具包。QT是一个跨平台的C应用程序开发框架&#xff0c;可以用于创建高性能、高可靠性、图形…

java 多线程环境空指针异常

示例代码 private Listener mlistener; public void onDestroy() { if (mListener ! null) { listener.remove(); // Null Pointer Exception at this line } } 在自动化测试中&#xff0c;这块会偶先一个空指针问题&#xff0c;如果根据activity生命周期来说&…

docker-compose通过volume恢复mysql数据

概述 docker rm是docker删除容器的命令。 会清空容器内的所有数据和配置&#xff0c;即真正的将容器清空并删除。 但是之前通过volume挂载到宿主机上是不受影响的。 docker rm -v如果是-v的命令那么会同时删除通过volume映射到宿主机上的文件 通过volume恢复数据 使用docke…