STM32F103C8T6实现串口通信+按键点灯
Posted mr-choa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32F103C8T6实现串口通信+按键点灯相关的知识,希望对你有一定的参考价值。
1、实现的效果
芯片复位,串口调试助手打印出:
芯片的唯一ID为: 67075433-49568770-670FF52
芯片flash的容量为: 64K
按下S2,灯翻转,同时打印OK
在串口助手命令端,发送命令,打印该命令
2、main.c
/************************************** * 文件名 :main.c * 描述 :通过串口调试软件,向板子发送数据,板子接收到数据后,立即回传给电脑。 * 实验平台:MINI STM32开发板 基于STM32F103C8T6 * 库版本 :ST3.0.0 *********************************************************/ #include "includes.h" extern u32 ChipUniqueID[3]; extern void bsp_Init(void); int main(void) { SystemInit(); //配置系统时钟为 72M bsp_Init(); //配置初始化 printf(" 芯片的唯一ID为: %X-%X-%X ", ChipUniqueID[0],ChipUniqueID[1],ChipUniqueID[2]); /* 输出芯片容量 */ printf(" 芯片flash的容量为: %dK ", *(__IO u16 *)(0X1FFFF7E0)); while (1) { if( Key_Scan(GPIOA,GPIO_Pin_0) == KEY_ON ) //判断KEY1是否按下 { GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13))));//LED1翻转 printf(" OK "); } } }
3、app.c
#include "app.h" u32 ChipUniqueID[3]; /* 获取芯片ID */ void Get_ChipID(void) { ChipUniqueID[0] = *(__IO u32 *)(0X1FFFF7F0); // 高字节 ChipUniqueID[1] = *(__IO u32 *)(0X1FFFF7EC); // ChipUniqueID[2] = *(__IO u32 *)(0X1FFFF7E8); // 低字节 } /* 描述 :重定向c库函数printf到USART1*/ int fputc(int ch, FILE *f) { /* 将Printf内容发往串口 */ USART_SendData(USART1, (unsigned char) ch); while (!(USART1->SR & USART_FLAG_TXE)); return (ch); } /*不精确的延时 */ void Delay(__IO u32 nCount) { for(; nCount != 0; nCount--); } /* 检测是否有按键按下 */ u8 Key_Scan(GPIO_TypeDef* GPIOx,u16 GPIO_Pin) { /*检测是否有按键按下 */ if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON ) { /*延时消抖*/ Delay(50000); if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON ) { /*等待按键释放 */ while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON); return KEY_ON; } else return KEY_OFF; } else return KEY_OFF; }
4、app.h
#ifndef __APP_H__ #define __APP_H__ #include "includes.h" #define KEY_ON 0 #define KEY_OFF 1 void Get_ChipID(void); void Delay(__IO u32 nCount); u8 Key_Scan(GPIO_TypeDef* GPIOx,u16 GPIO_Pin); #endif
5、bsp.c
#include "bsp.h" /******************************************************************************* * Function Name : RCC_Configuration * Description : Configures the different system clocks. * Input : None * Output : None * Return : None *******************************************************************************/ void RCC_Configuration(void) { ErrorStatus HSEStartUpStatus; /* Setup the microcontroller system. Initialize the Embedded Flash Interface, initialize the PLL and update the SystemFrequency variable. */ //SystemInit(); /* RCC system reset(for debug purpose) */ RCC_DeInit(); /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus == SUCCESS) { /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Flash 2 wait state */ FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */ RCC_PCLK1Config(RCC_HCLK_Div2); /* ADCCLK = PCLK2/8 */ RCC_ADCCLKConfig(RCC_PCLK2_Div8); /* PLLCLK = 8MHz * 9 = 72 MHz */ RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { } /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while(RCC_GetSYSCLKSource() != 0x08) { } } /* Enable GPIOx clock */ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOG , ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOF , ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE , ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD , ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC , ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA , ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO , ENABLE ); /* Enable DMA clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* Enable ADC1 and GPIOC clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE); /* Enable USART1&2 clocks */ // Enable GPIOA clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE ); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE ); /* Enable USART3 clocks */ // Enable GPIOB clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE ); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE ); /* Enable the FSMC Clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); /* Enable TIM1 clock source */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); } /******************************************************************************* * Function Name : GPIO_Configuration * Description : Configures the different GPIO ports. * Input : None * Output : None * Return : None *******************************************************************************/ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* USART1 使用IO端口配置 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PA9==USART1_TX复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //PA10==USART1_RX浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PA0按键端口配置为上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化端口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC端口 GPIO_SetBits(GPIOC, GPIO_Pin_13); // 关闭所有LED } /******************************************************************************* * Function Name : NVIC_Configuration * Description : Configures Vector Table base location. * Input : None * Output : None * Return : None *******************************************************************************/ #define VECT_TAB_FLASH void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; #if defined (VECT_TAB_RAM) /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); #elif defined(VECT_TAB_FLASH_IAP) NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x2000); #else /* VECT_TAB_FLASH */ /* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00000); #endif /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Enable the USART1 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;;//串口1中断 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//子优先级位1 NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//子优先级位1 NVIC_Init(&NVIC_InitStructure);//④中断初始化函数 /* Enable the USART2 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable the USART3 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable the EXTI2 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void USART1_Configuration(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; //波特率设置:115200 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位数设置:8位 USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位设置: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); //初始化USART1 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//④开启接收中断!!!! USART_Cmd(USART1, ENABLE);// USART1使能 /* 如下语句解决第1个字节无法正确发送出去的问题 */ USART_ClearFlag(USART1, USART_FLAG_TC); // 清标志 } void USART2_Configuration(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 9600; 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_InitStructure.USART_Mode = USART_Mode_Rx; /* Configure the USART2 */ USART_Init(USART2, &USART_InitStructure); /* Enable USART2 Receive interrupt */ USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); /* Enable the USART2 */ USART_Cmd(USART2, ENABLE); /* 如下语句解决第1个字节无法正确发送出去的问题 */ USART_ClearFlag(USART2, USART_FLAG_TC); // 清标志 } void USART3_Configuration(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; 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; /* Configure the USART3 */ USART_Init(USART3, &USART_InitStructure); /* Enable USART3 Receive interrupt */ USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); /* Enable the USART3 */ USART_Cmd(USART3, ENABLE); /* 如下语句解决第1个字节无法正确发送出去的问题 */ USART_ClearFlag(USART3, USART_FLAG_TC); // 清标志 } void TIM1_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //皮變TIMER1胤为輪私欠 TIM_DeInit(TIM1); TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler = 0x00; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV4; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // Time base configuration //TIM_ETRClockMode2Config(TIM1, TIM_ExtTRGPSC_DIV8, TIM_ExtTRGPolarity_NonInverted, 0x0F); TIM_ETRClockMode2Config(TIM1, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_Inverted, 0x0F); TIM_SetCounter(TIM1, 0); TIM_Cmd(TIM1, ENABLE); } //BSP初始化函数 void bsp_Init(void) { RCC_Configuration(); //时钟配置 GPIO_Configuration(); //端口配置 USART1_Configuration(); //接口配置 // USART2_Configuration(); //接口配置 // USART3_Configuration(); //接口配置 // FSMC_SRAM_Init(); //总线配置 // EXTI_Configuration(); //中断配置 // ADC_Configuration(); //采样配 // TIM1_Configuration(); //定时器配置 NVIC_Configuration(); //中断配置 Get_ChipID(); }
6、bsp.h
#ifndef __BSP_H__ #define __BSP_H__ #include "includes.h" void RCC_Configuration(void); void GPIO_Configuration(void); void NVIC_Configuration(void); void USART1_Configuration(void); void USART2_Configuration(void); void USART3_Configuration(void); void TIM1_Configuration(void); void bsp_Init(void); #endif
7、部分stm32f10x_it.c
void USART1_IRQHandler(void) { u8 res; if(USART_GetITStatus(USART1,USART_IT_RXNE))//判断是否有接受中断! { //串口数据收发函数⑦ res= USART_ReceiveData(USART1); USART_SendData(USART1,res); } }
以上是关于STM32F103C8T6实现串口通信+按键点灯的主要内容,如果未能解决你的问题,请参考以下文章
STM32学习笔记 二基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发
STM32学习笔记 二基于STM32F103C8T6和STM32CubeMX实现UART串口通信数据收发
STM32学习笔记 一基于STM32F103C8T6最小系统板和STM32CubeMX实现板载LED灯循环闪烁
三实战小例程 基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方