C8T6超绝模块--USART串口通信

C8T6超绝模块–USART串口通信

注意USART的引脚请自行查阅相应的数据手册

本模块主要实现功能
实现开发板与电脑通信,在开发板上电时通过 USART 发送一串字符串给电脑,然后开发板进入中断接收等待状态,如果电脑有发送数据过来,开发板就会产生中断,我们在中断服务函数接收数据,并马上把数据返回发送给电脑

大纲

  1. USART原理和结构体讲解
  2. 代码流程(收发数据)
  3. 代码流程(实现控制)

具体案例

USART原理和结构体讲解

在USART–串口通信一文中有详细解释,这里就不做详细解释

代码流程(收发数据)

USART.H

这是使用的宏定义

#ifndef __BSP_USART_H
#define __BSP_USART_H

#include "stm32f10x.h"
#include 

/** 
  * 串口宏定义,不同的串口挂载的总线和IO不一样,移植时需要修改这几个宏
	* 1-修改总线时钟的宏,uart1挂载到apb2总线,其他uart挂载到apb1总线
	* 2-修改GPIO的宏
  */
	
#define	DEBUG_USART1		1
#define	DEBUG_USART2		0
#define	DEBUG_USART3		0
#define	DEBUG_USART4		0
#define	DEBUG_USART5		0
	
	
#if DEBUG_USART1
// 串口1-USART1
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler

#elif DEBUG_USART2
// 串口2-USART2
#define  DEBUG_USARTx                   USART2
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART2
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_2
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_3

#define  DEBUG_USART_IRQ                USART2_IRQn
#define  DEBUG_USART_IRQHandler         USART2_IRQHandler

#elif DEBUG_USART3
// 串口3-USART3
#define  DEBUG_USARTx                   USART3
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART3
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOB)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOB   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_10
#define  DEBUG_USART_RX_GPIO_PORT       GPIOB
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_11

#define  DEBUG_USART_IRQ                USART3_IRQn
#define  DEBUG_USART_IRQHandler         USART3_IRQHandler

#elif DEBUG_USART4
// 串口4-UART4
#define  DEBUG_USARTx                   UART4
#define  DEBUG_USART_CLK                RCC_APB1Periph_UART4
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOC)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOC   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_10
#define  DEBUG_USART_RX_GPIO_PORT       GPIOC
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_11

#define  DEBUG_USART_IRQ                UART4_IRQn
#define  DEBUG_USART_IRQHandler         UART4_IRQHandler


#elif DEBUG_USART5
// 串口5-UART5
#define  DEBUG_USARTx                   UART5
#define  DEBUG_USART_CLK                RCC_APB1Periph_UART5
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOC   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_12
#define  DEBUG_USART_RX_GPIO_PORT       GPIOD
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_2

#define  DEBUG_USART_IRQ                UART5_IRQn
#define  DEBUG_USART_IRQHandler         UART5_IRQHandler

#endif


void USART_Config(void);
void Usart_SendByte(USART_TypeDef* pUSARTx,uint8_t data);
void Usart_SendHalfWord(USART_TypeDef * pUSARTx,uint16_t data);
void Usart_SendArray(USART_TypeDef * pUSARTx,uint8_t *array,uint8_t num);
void Usart_SendStr(USART_TypeDef * pUSARTx,uint8_t *str);



#endif

USART.C

首先设置中断的优先级

static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitSructure;
	
	// 进行嵌套向量中断控制器的选择
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	// 配置USART为中断源
	NVIC_InitSructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
	
	// 抢断优先级
	NVIC_InitSructure.NVIC_IRQChannelPreemptionPriority = 1;
	
	// 子优先级
	NVIC_InitSructure.NVIC_IRQChannelSubPriority = 1;
	
	// 使能中断
	NVIC_InitSructure.NVIC_IRQChannelCmd = ENABLE;
	
	// 初始化配置NVIC
	NVIC_Init(& NVIC_InitSructure);
}

其次是USART串口的初始化

void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	// 打开串口GPIO的时钟
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK,ENABLE);
	
	// 打开串口外设的时钟
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK,ENABLE);
	
	// 初始化GPIO, 将USART Tx配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT,&GPIO_InitStructure);
	
	// 将USART Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT,&GPIO_InitStructure);
	
	// 配置串口的工作的参数
	// 配置波特率
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	// 配置字数据长
	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(DEBUG_USARTx,& USART_InitStructure);
	
	// 串口中断优先级配置
	NVIC_Configuration();
	
	// 使能串口接收中断
	USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,ENABLE);
	
	// 使能串口(其实是打开UE)
	USART_Cmd(DEBUG_USARTx,ENABLE);
	
}

注意初始化串口时,分别初始化串口的TX(推挽复用)RX(浮空输入)两个引脚后,再配置串口的结构体的参数。再调用前面的设置中断的优先级。使能串口接收中断
上面完成的是串口初始化的代码,下面是具体实现数据发送的功能函数

// 发送一个字节
void Usart_SendByte(USART_TypeDef* pUSARTx,uint8_t data)
{
	
	USART_SendData(pUSARTx,data);
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE) == RESET);
	
}

// 发射两个字节
void Usart_SendHalfWord(USART_TypeDef * pUSARTx,uint16_t data)
{
	uint8_t temp_h,temp_l;
	
	temp_h = (data & 0xff00) >> 8;
	temp_l = data & 0xff;
	USART_SendData(pUSARTx,temp_h);
	while( USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE) == RESET );
	
	USART_SendData(pUSARTx,temp_l);
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE));
	
}


// 发送8位数据的数组
void Usart_SendArray(USART_TypeDef * pUSARTx,uint8_t *array,uint8_t num)
{
	uint8_t i;
	for(i = 0; i < num;i++)
 { 
	Usart_SendByte(pUSARTx,*array++);
 }
 
 while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET);
}


// 发送字符串
void Usart_SendStr(USART_TypeDef * pUSARTx,uint8_t *str)
{
	uint8_t i = 0;
	do
	{
		Usart_SendByte(pUSARTx,*(str + i));
		i++;
	}while(*(str + i) != '\0');
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET);
	
}

// 重定向c库函数printf到串口,重定向后可使用printf函数

int fputc(int ch,FILE *f)
{
	// 发送一个字节到串口
	USART_SendData(DEBUG_USARTx,(uint8_t)ch);
	
	// 等待发送完成
	while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TXE) == RESET);
	
	return (ch);
}

// 重定向c库函数scanf到串口,重写向后可使用的scanf,getchar函数
int fgetc(FILE *f)
{
	// 等待串口输入数据
	while (USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_RXNE) == RESET);
	
	return (int)USART_ReceiveData(DEBUG_USARTx);
}

USART中断服务函数

// 串口中断函数
void DEBUG_USART_IRQHandler(void)
{
	uint8_t	ucTemp;
	if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE) != RESET)
	{
		ucTemp = USART_ReceiveData(DEBUG_USARTx);
		USART_SendData(DEBUG_USARTx,ucTemp);
	}

}

这是串口完成接收时,接收到数据后,存储在ucTemp然后再发送回来他接收到的数据

main

# include "stm32f10x.h"

#include "bsp_led.h"
#include "bsp_usart.h"

void Delay( uint32_t count)
{
	for(;count != 0;count--);
}

int main(void)
{
	USART_Config();	
	
printf("串口printf函数测试\n");
putchar('p');	

	
	while(1){
	
	
	}
	
}

其实这里主要还是就是完成串口的初始化

代码流程(实现控制)

主要的串口初始化和接收函数和上面一样
我们这里主要通过接收到的数据控制小灯
小灯初始化请见:C8T6超绝模块–点亮小灯
而与上面的差别,主要体现在主函数里面

main

# include "stm32f10x.h"

#include "bsp_led.h"
#include "bsp_usart.h"


int main(void)
{
	USART_Config();
	uint8_t ch;
	LED_GPIO_Config();
	
	
	while(1){
		
		printf("这是串口控制LED的程序\n");
		ch = getchar();
		printf("ch=%c\n",ch);
		
		switch(ch)
		{
			case '1':
				LED_G(ON);
				break;
			case '2':
				LED_G(OFF);
			
			break;
			default:LED_G(OFF);
		}
	}
	
}

这里主要通过getchar()来把USART返回的值存储到ch中,然后再通过ch的值进行判断,来进行点亮或者熄灭小灯

但是这里要注意点一点是:
我们使用这个getchar()要实现返回接收到的串口数据值,需要实现他的重定向
在上面的代码主要体现在这一块

// 重定向c库函数scanf到串口,重写向后可使用的scanf,getchar函数
int fgetc(FILE *f)
{
	// 等待串口输入数据
	while (USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_RXNE) == RESET);
	
	return (int)USART_ReceiveData(DEBUG_USARTx);
}

判断是否接受完成,如果接收完成,就返回接收到的值

你可能感兴趣的:(STM32模块示例代码,单片机,嵌入式硬件)