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
```