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); //³õʼ»¯USART1
RCC_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_LEN
u16 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.9
GPIO_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.10
GPIO_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();
#endif
if(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_OS
OSIntExit();
#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
```