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光立方

三实战小例程 基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方

三实战小例程 基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方