USARTのSTM32ノート(シリアル)

EDITORIAL:
個人的な要約であるとして間違っては、私を修正してください場合は、この記事の目的は、将来の問い合わせを容易にするため、バックアップを要約する;加えて、インターネット、書籍、各種マニュアルの内容のほとんどは、侵害を通知し、すぐに削除投稿を喜ばなければなりません謝罪します。

 

ディレクトリ

まず、シリアル通信

二つ、トランシーバのUSART機能ブロック図

三、USARTモードの設定

第四に、コードの実装プロセス

五、のprintf()関数リダイレクト

第六に、総プロジェクトコード


 

まず、シリアル通信

ここでは、もはや面倒が前の章を参照してください示していないです  UART / USRAT、I2C、SPI通信リテラシーを

 

二つ、トランシーバのUSART機能ブロック図

 

三、USARTモードの設定

1、各モードはサポートしています

2、I / Oの多重化の設定

 

第四に、コードの実装プロセス

UARTは、我々は必要が導入するかどうかを決定することができる場合は、このルーチンでは、我々は一般的に使用されるUART(非同期シリアルポート)、およびUSART(同期シリアルインターフェース)が、複数のクロックライン、ように、配置されました受信ノード完了、タイムアウト時間を決定することができる、決意などターミネーター

設定する前に、我々は、第一の受信の構造を定義します

#define RxBUFFER_SIZE   	0xFF

typedef struct
{
	uint8_t RxBuffer[RxBUFFER_SIZE];		// 接收暂存缓冲区
	__IO uint8_t RxCounter;				// 接收数据个数
	uint8_t Receiving_Time;				// 接收时间
	uint8_t Frame_flag;				// 一帧完成标志
}EVAL_COMx_TypeDef;

送信バッファーので、我々は、(すべての後に、場合にのみ、シングルショット送信することができる)を共有することができるので、我々はただのような配列を定義します

#define TxBUFFER_SIZE   	100

uint8_t g_TxCounter = 0; 			// 发送数据个数
uint8_t TxBuffer[TxBUFFER_SIZE] = {0};		// 发送暂存缓冲区

さて、今あなたは私たちのUART、それを構成するために開始します

1、UART1機能:

#define EVAL_COM1		USART1

/************************************************
函数名称 : UART1_Comfig
功    能 : UART1端口配置
参    数 : Baudrate ---- 波特率
返 回 值 : 无
*************************************************/
void UART1_Comfig( uint32_t Port )
{
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* config GPIOA clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
    /* config USART1 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    /* USART1 GPIO config */
    /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure USART1 Rx (PA.10) as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Enable the USART1 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* USART1 mode config */
    USART_InitStructure.USART_BaudRate = Port;                    // 获取波特率
    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(EVAL_COM1, &USART_InitStructure);

    USART_ITConfig(EVAL_COM1, USART_IT_RXNE, ENABLE);             // 使能串口接收中断
    USART_Cmd(EVAL_COM1, ENABLE);                                 // 使能串口
}

2、治療を受けて割り込み:

/************************************************************************/
/*            STM32F10x USART Interrupt Handlers                        */
/************************************************************************/

/**
  * @brief  This function handles USART1 global interrupt request.
  * @param  None
  * @retval None
  */
void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)    // 判断接收
    {
        /* Read one byte from the receive data register */
        Usart1.RxBuffer[Usart1.RxCounter++] = (USART_ReceiveData(EVAL_COM1) & 0x7F);  // 获取数据

        if(Usart1.RxCounter >= RxBUFFER_SIZE)    // 判断是否超出接收最大长度
        {
//            /* Disable the EVAL_COM1 Receive interrupt */
//            USART_ITConfig(EVAL_COM1, USART_IT_RXNE, DISABLE);

            Usart1.Frame_flag = 0;               // 接收完成标志清零
            Usart1.RxCounter = 0;                // 计数清零
            Usart1.Receiving_Time = 0;           // 接收超时时间清零
        }
        Usart1.Receiving_Time = 2;               // 设置超时判定时间
    }

    /* 因为我们不去利用中断进行发送,所以下面的操作屏蔽掉 */
//  if(USART_GetITStatus(EVAL_COM1, USART_IT_TXE) != RESET)
//  {
//    /* Write one byte to the transmit data register */
//    USART_SendData(EVAL_COM1, TxBuffer[TxCounter++]);

//    if(TxCounter == RxBUFFER_SIZE)
//    {
//      /* Disable the EVAL_COM1 Transmit interrupt */
//      USART_ITConfig(EVAL_COM1, USART_IT_TXE, DISABLE);
//    }
//  }
}

ここで、受信側かタイムアウト決意と同様に、次のようにもタイマ決意に、それが決定されます。

if(Usart1.Receiving_Time)
{
    Usart1.Receiving_Time--;
    if(!Usart1.Receiving_Time)
        Usart1.Frame_flag = 1;
}

データはあなたがタイムアウト係数を設定するかによって、完了したとみなされたときについて

図3に示すように、変速機出力処理:

/************************************************
函数名称 : USART_SendByte
功    能 : 串口字符发送
参    数 : c ---- 发送的数据
返 回 值 : 无
*************************************************/
void USART_SendByte( USART_TypeDef* USARTx, uint8_t c )
{     
	USART_SendData(USARTx, c);
	
	while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}

/************************************************
函数名称 : USART_SendString
功    能 : 串口字符串发送
参    数 : USARTx ---- 串口
			pData ---- 字符串
			Length ---- 长度
返 回 值 : 无
*************************************************/
void USART_SendString( USART_TypeDef* USARTx, const uint8_t *pData, uint16_t Length )
{
    while(Length--)
    {
        USART_SendByte(USARTx, *pData);
        pData++;
    }
}

/************************************************
函数名称 : USART_Printf
功    能 : 串口打印输出
参    数 : USARTx ---- 串口
			String	---- 字符串
返 回 值 : 无
*************************************************/
void USART_Printf( USART_TypeDef* USARTx, char *String )
{
    do
    {
        USART_SendByte(USARTx, *String);
        String++;
    }while((*String) != '\0');
}

 

五、のprintf()関数リダイレクト

ルーチンの公式では、main.cのファイルの次のこのルーチンの機能を見ることができます:

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
    /* Place your implementation of fputc here */
    /* e.g. write a character to the USART */
    USART_SendData(EVAL_COM1, (uint8_t) ch);

    /* Loop until the end of transmission */
    while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)
    {}

    return ch;
}

私たちは、これはCライブラリのprintf関数は、公式にリダイレクトされていることを知っているコメントを参照してくださいすることはUSARTテンプレートを与え、その後、我々はそれを変更、これは以下のようになります。

#define DEBUG_UART		USART1

/************************************************
函数名称 : fputc
功    能 : 重定向 c库函数 printf到 DEBUG_UART
参    数 : ch
返 回 值 : 无
*************************************************/
int fputc(int ch, FILE *f)
{
    /* 发送一个字节数据到 DEBUG_UART */
    USART_SendData(DEBUG_UART, (uint8_t) ch);

    /* 等待发送完毕 */
    while (USART_GetFlagStatus(DEBUG_UART, USART_FLAG_TXE) == RESET);

    return (ch);
}

/************************************************
函数名称 : fgetc
功    能 : 重定向 c库函数 scanf到 DEBUG_UART
参    数 : f ---- 文件
返 回 值 : 无
*************************************************/
int fgetc(FILE *f)
{
    /* 等待 DEBUG_UART输入数据 */
    while (USART_GetFlagStatus(DEBUG_UART, USART_FLAG_RXNE) == RESET);

    return (int)USART_ReceiveData(DEBUG_UART);
}

 

第六に、総プロジェクトコード

bsp_uart.cのソースファイル

#include "bsp_uart.h"


uint8_t g_TxCounter = 0; 				// 发送数据个数
uint8_t TxBuffer[TxBUFFER_SIZE] = {0};	// 发送暂存缓冲区

EVAL_COMx_TypeDef Usart1,Usart2;

/************************************************
函数名称 : UART1_Comfig
功    能 : UART1端口配置
参    数 : Baudrate ---- 波特率
返 回 值 : 无
*************************************************/
void UART1_Comfig( uint32_t Port )
{
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* config GPIOA clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
    /* config USART1 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    /* USART1 GPIO config */
    /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure USART1 Rx (PA.10) as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Enable the USART1 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* USART1 mode config */
    USART_InitStructure.USART_BaudRate = Port;                    // 获取波特率
    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(EVAL_COM1, &USART_InitStructure);

    USART_ITConfig(EVAL_COM1, USART_IT_RXNE, ENABLE);             // 使能串口接收中断
    USART_Cmd(EVAL_COM1, ENABLE);                                 // 使能串口
}

/************************************************
函数名称 : USART_SendByte
功    能 : 串口字符发送
参    数 : c ---- 发送的数据
返 回 值 : 无
*************************************************/
void USART_SendByte( USART_TypeDef* USARTx, uint8_t c )
{     
	USART_SendData(USARTx, c);
	
	while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}

/************************************************
函数名称 : USART_SendString
功    能 : 串口字符串发送
参    数 : USARTx ---- 串口
			pData ---- 字符串
			Length ---- 长度
返 回 值 : 无
*************************************************/
void USART_SendString( USART_TypeDef* USARTx, const uint8_t *pData, uint16_t Length )
{
    while(Length--)
    {
        USART_SendByte(USARTx, *pData);
        pData++;
    }
}

/************************************************
函数名称 : USART_Printf
功    能 : 串口打印输出
参    数 : USARTx ---- 串口
			String	---- 字符串
返 回 值 : 无
*************************************************/
void USART_Printf( USART_TypeDef* USARTx, char *String )
{
    do
    {
        USART_SendByte(USARTx, *String);
        String++;
    }while((*String) != '\0');
}


/************************************************
函数名称 : fputc
功    能 : 重定向 c库函数 printf到 DEBUG_UART
参    数 : ch
返 回 值 : 无
*************************************************/
int fputc(int ch, FILE *f)
{
    /* 发送一个字节数据到 DEBUG_UART */
    USART_SendData(DEBUG_UART, (uint8_t) ch);

    /* 等待发送完毕 */
    while (USART_GetFlagStatus(DEBUG_UART, USART_FLAG_TXE) == RESET);

    return (ch);
}

/************************************************
函数名称 : fgetc
功    能 : 重定向 c库函数 scanf到 DEBUG_UART
参    数 : f ---- 文件
返 回 值 : 无
*************************************************/
int fgetc(FILE *f)
{
    /* 等待 DEBUG_UART输入数据 */
    while (USART_GetFlagStatus(DEBUG_UART, USART_FLAG_RXNE) == RESET);

    return (int)USART_ReceiveData(DEBUG_UART);
}


/************************************************************************/
/*            STM32F10x USART Interrupt Handlers                        */
/************************************************************************/

/**
  * @brief  This function handles USART1 global interrupt request.
  * @param  None
  * @retval None
  */
void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET)    // 判断接收
    {
        /* Read one byte from the receive data register */
        Usart1.RxBuffer[Usart1.RxCounter++] = (USART_ReceiveData(EVAL_COM1) & 0x7F);  // 获取数据

        if(Usart1.RxCounter >= RxBUFFER_SIZE)    // 判断是否超出接收最大长度
        {
//            /* Disable the EVAL_COM1 Receive interrupt */
//            USART_ITConfig(EVAL_COM1, USART_IT_RXNE, DISABLE);

            Usart1.Frame_flag = 0;               // 接收完成标志清零
            Usart1.RxCounter = 0;                // 计数清零
            Usart1.Receiving_Time = 0;           // 接收超时时间清零
        }
        Usart1.Receiving_Time = 2;               // 设置超时判定时间
    }

    /* 因为我们不去利用中断进行发送,所以下面的操作屏蔽掉 */
//  if(USART_GetITStatus(EVAL_COM1, USART_IT_TXE) != RESET)
//  {
//    /* Write one byte to the transmit data register */
//    USART_SendData(EVAL_COM1, TxBuffer[TxCounter++]);

//    if(TxCounter == RxBUFFER_SIZE)
//    {
//      /* Disable the EVAL_COM1 Transmit interrupt */
//      USART_ITConfig(EVAL_COM1, USART_IT_TXE, DISABLE);
//    }
//  }
}


/*---------------------------- END OF FILE ----------------------------*/


 

bsp_uart.hのヘッダファイル

#ifndef __BSP_UART_H
#define __BSP_UART_H


#include <stdio.h>
#include "stm32f10x.h"

#define DEBUG_UART			USART1
#define EVAL_COM1			USART1
#define EVAL_COM2			USART2

#define TxBUFFER_SIZE   	100
#define RxBUFFER_SIZE   	0xFF

typedef struct
{
	uint8_t RxBuffer[RxBUFFER_SIZE];		// 接收暂存缓冲区
	__IO uint8_t RxCounter;				// 接收数据个数
	uint8_t Receiving_Time;				// 接收时间
	uint8_t Frame_flag;				// 一帧完成标志
}EVAL_COMx_TypeDef;
extern EVAL_COMx_TypeDef Usart1,Usart2;

extern uint8_t g_TxCounter;
extern uint8_t TxBuffer[TxBUFFER_SIZE];

void UART1_Comfig( uint32_t Baudrate );
void USART_SendByte( USART_TypeDef* USARTx, uint8_t c );
void USART_SendString( USART_TypeDef* USARTx, const uint8_t *pData, uint16_t Length );
void USART_Printf( USART_TypeDef* USARTx, char *String );


#endif	/* __BSP_UART_H */


/*---------------------------- END OF FILE ----------------------------*/


 

main.cののファイル

/**
  ******************************************************************************
  * @file    Project/STM32F10x_StdPeriph_Template/main.c
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdio.h>
#include "bsp.h"
#include "bsp_uart.h"



/* Private functions ---------------------------------------------------------*/

const uint32_t Baudrate_1 = 115200;		// 波特率设置	支持的波特率:115200,19200,9600,38400,57600,1200,2400,4800
const uint32_t Baudrate_2 = 115200;		// 波特率设置	支持的波特率:115200,19200,9600,38400,57600,1200,2400,4800

/************************************************
函数名称 : main
功    能 : 主函数入口
参    数 : 无
返 回 值 : 无
*************************************************/
int main(void)
{
    /* Initial Configuration */
    SystemInit();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SysTick_Init();
    UART1_Comfig(Baudrate_1);
	
    /* -------- End -------- */
	
	
    /* Infinite loop */
    while (1)
    {
        if(Usart1.Frame_flag)
        {
            Usart1.Frame_flag = 0;
            USART_SendString(USART1, Usart1.RxBuffer, Usart1.RxCounter);
            printf("\n>>>>> 接收成功\n");
            Usart1.RxCounter = 0;
        }
    }
}

#if 0
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
    /* Place your implementation of fputc here */
    /* e.g. write a character to the USART */
    USART_SendData(EVAL_COM1, (uint8_t) ch);

    /* Loop until the end of transmission */
    while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)
    {}

    return ch;
}

#endif

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}
#endif

/**
  * @}
  */


/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

在这里,没有把 UART的串口中断放到 stm32f10x_it.c文件中,是个人觉得统一放在自定义的 uart文件中易于管理,包括后面的 Time、ADC等,而那些 I/O中断就放回 stm32f10x_it.c文件中(主要是觉得不可能一些 LED、Key什么的,又创一个 bsp文件给她吧,这样就太太累赘了);还有就是那个超时判定的那部分在定时器中代码并没有贴出来(主要是还没发 Time的篇章,等待下一篇吧!)

发布了40 篇原创文章 · 获赞 14 · 访问量 1万+

おすすめ

転載: blog.csdn.net/qq_42992084/article/details/104098531