> 项目环境Environment

基于以下环境测试所得,不保证完全兼容表格以外的环境,需略作修改

设备/环境版本Version补充说明Description
STM32F103C8T6 /> 波特律动 | kk画的白色板子,颜值很高
Keil uVision55.39.0.0标准库+Keil5开发 | Hal库在学习中
OLED驱动1.2> 江协科技 | 同款OLED屏幕,标准库最优选择
串口助手1.1> 江协科技 | 免安装功能完善

> 项目配置list

以下描述了项目结构与说明,点击此处标题可跳转至Github打包下载源码

文件夹补充说明Description
INC存放标准库及项目.h头文件
MDKKeil5项目文件目录
OUTPUT链接中间文件、AXF烧录文件等输出目录
SRE存放主函数及项目其余.c文件

> Keil配置

Project -> Options for Target 填写指南

keil选项填写内容
Output选择目录「OUTPUT」,生成HEX文件
C/C++Define :
USE_STDPERIPH_DRIVER,STM32F10X_MD
Language/ Code Generation :
> C99 mode
Include Paths :
..\INC
..\..\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
..\..\Libraries\STM32F10x_StdPeriph_Driver\inc
DebugST-Link Debugger – Port : SW

> 测试效果

初始化串口/OLED后立即接收一条[Hello Keil5!],接下来的每一条语句[以x结尾或满20个字符]发送至STM32并显示在OLED上

> 项目分析

摘取关键内容进行记录、巩固知识点 [右下角标直达Github]

C
#include "stm32f10x_it.h"
#include "usart.h"
#include "delay.h"
#include "oled.h"

uint32_t TimingDelay = 0; //Delay函数 中断实现 递减
uint8_t USART_RXBUF[20]; //接收数组
extern uint8_t RXOVER;

int main(void)
{
	uint8_t i;
	USART_Config(); //串口中断 | RX | TX 配置
    
  SysTick_Config(SystemCoreClock/1000);  //1ms中断一次
    
	USART_SendString((int8_t*)"Hello Keil5!\r\n"); //测试串口发送
    
	/*OLED初始化*/
	OLED_Init();
	
	while(1) {			
		if(RXOVER == 1) { //接收到数据时激活
            /*在(0, 0)位置显示发送字符串,字体大小为8*16点阵*/
            OLED_ShowString(0, 0, (char*)USART_RXBUF, OLED_8X16);
            
            /*调用OLED_Update函数,将OLED显存数组的内容更新到OLED硬件进行显示*/
            OLED_Update();
            
            /*延时3000ms,观察现象*/
            Delay_ms(3000);

			for(i = 0; i < 20; ++i) {
				USART_RXBUF[i] = 0; //清空接收数组
			}
            
			RXOVER = 0;
			USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
		}
	}
}
main.c
C
#include "usart.h"
#include "stm32f10x.h"

#define USART_FLAG_TXE ((uint16_t)0x0080)

void USART_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
	
	  //时钟使能
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    
    //Interrupt
	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	
	  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	  NVIC_Init(&NVIC_InitStructure);
	
    //TX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    //RX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //比特率参数对等设定
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART2, &USART_InitStructure);
	
    USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
    USART_Cmd(USART2, ENABLE);
}

void USART_SendString(int8_t *str) //等待机制发送数据
{
    uint8_t index = 0;
    do {
        USART_SendData(USART2, str[index]);
        while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
        ++index;
    } while(str[index]);   
}
usart.c
C
void USART2_IRQHandler(void)
{
	uint8_t temp;
	
	if(USART_GetFlagStatus(USART2, USART_IT_RXNE) != RESET) {
		USART_ClearITPendingBit(USART2, USART_IT_RXNE);
		temp = USART_ReceiveData(USART2);
		
		if((temp == 'x') || (RXCONT == 20)) { //终止位
			RXCONT = 0;
			RXOVER = 1;
			USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);
		}
		else{
			USART_RXBUF[RXCONT] = temp;
			++RXCONT;			
		}
			
	}
}
stm32f10x_it.c