天天看点

STM32F429之UART使用

#if 1

/// 重定向c库函数printf到USART1

int fputc(int ch, FILE *f)

{

        USART_SendData(USART1, (uint8_t) ch);

        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);        

        return (ch);

}

/// 重定向c库函数scanf到USART1

int fgetc(FILE *f)

{

        while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

        return (int)USART_ReceiveData(USART1);

}

#endif

USART 只需两根信号线即可完成双向通信,对硬件要求低,使得很多模块都预留USART 接口来实现与其他模块或者控制器进行数据传输,比如 GSM 模块, WIFI 模块、蓝牙模块

APB2(最高 90MHz)                                     APB1(最高 45MHz)
USART1 USART6 USART2 USART3 UART4 UART5 UART7 UART8
TX PA9/PB6 PC6/PG14 PA2/PD5

PB10/PD8

/PC10

PA0/PC10 PC12 PF7/PE8 PE1
RX PA10/PB7 PC7/PG9 PA3/PD6

PB11/PD9

/PC11

PA1/PC11 PD2 PF6/PE7 PE0
SCLK PA8 PG7/PC8 PA4/PD7

PB12/PD10

/PC12

nCTS PA11 PG13/PG15 PA0/PD3 PB13/PD11
nRTS PA12 PG8/PG12 PA1/PD4 PB14/PD12

串口1收发数据配置

配合原子的 usmart可以方便的进行调试,使用usmart可以通过串口调用函数,可以传参数非常方便。

void NVIC_Configuration_1(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	/* 配置 NVIC 为优先级绿1 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	/* 配置中断源:按键 1 */
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	/* 配置抢占优先级: 1 */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
	/* 配置子优先级_1 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
	/* 使能中断通道 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

void USART1_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	/* config USART1 clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, 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);
	
	/* USART1 mode config */
	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;
	USART_Init(USART1, &USART_InitStructure);
	NVIC_Configuration_1();
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	USART_Cmd(USART1, DISABLE);
	(void)USART1->SR; (void)USART1->DR;
	USART_ClearFlag(USART1, USART_FLAG_TC);
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	USART_Cmd(USART1, ENABLE);

}



void USART1_IRQHandler_FUN(void)
{

	u8 data;

	(void)USART1->SR;   //Error clear;
	data =	(u8)(USART1->DR & (u16)0x01FF);
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	resevice_buf(data);//
	get_buf_usart1[get_usart1_i] = data;
	USART_SendData(USART1, data);	
	get_usart1_i++;
	if(get_buf_usart1[0] != 0xFF)
	{
		get_usart1_i=0;
	}
		
	if(get_usart1_i==4)
	{	
		AnalizingBuf2();
		get_usart1_i = 0;
		gRxHostBufferFlush(4,get_buf_usart1);
	}
	
}
/// 重定向c库函数printf到USART1
int fputc(int ch, FILE *f)
{
		/* 发送一个字节数据到USART1 */
		USART_SendData(USART1, (uint8_t) ch);
		
		/* 等待发送完毿*/
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}

/// 重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
		/* 等待串口1输入数据 */
		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(USART1);
}
           

使用USART1进行串口调试,打印信息到电脑

程序是如何找到中断服务程序呢?在启动文件startup_stm32f10x_md.s中有这样一段代码,汇编DCD USART1_IRQHandler 

STM32F429之UART使用

stm32串口调试是一个很好的方法

一般有4个上的串口,可以将printf函数重定向到一个UART。这样就可以用printf函数将单片机的数据打印到PC上的超级终端或串口调试助手。

可以通过串口发送一些参数方便调试,可以用一个协议易于操作

//定义一个协议,关于数据收发的

//第一位:判断数据是否正确

//第二位:判断数据是否正确

//第三位:存放参数多少

//第四位:参数[1]

//第五位:参数[2]

//第n位:参数[n]

char get_From_PC[64];

bool Buffur_Full = FALSE;//定义成全局变量

char buf[64];//定义成全局变量

int buf_conut =0

void DEBUG_USART_IRQHandler(void)

{

    uint8_t ucTemp;

    if (USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) {

        buf[buf_conut++] = USART_ReceiveData( USART1 );

        PacketCheck();

    }

}

void BufferFlush(u32 BufferSize){

    for(u32 counter=0; counter<BufferSize; counter++) buf[counter] = 0;

}

void PacketCheck(void)

{

    int para_length = 0;

    //Header Check

    if(buf[0]!=0xff){ BufferFlush(buf_conut); buf_conut=0; return; }

    else if(buf_conut==1) return;

        if(buf[1]!=0xff){ BufferFlush(buf_conut); buf_conut=0; return; }

        else if(buf_conut==2) return;

    if(buf_conut>2)

    {    

        para_length = buf[2];

        if(buf_conut - 2> para_length)

        {

            for(int i= 0;i<para_length ;i++)

            {

                get_From_PC[i] = buf[i+3];

            }

        }

        if(buf_conut == para_length +2)

        {

            Buffur_Full = TURE;

            gRxHostBufferFlush(buf_conut);

            buf_conut = 0;

        }

    }

}

static void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

工作模式配置

//USART 初始化配置

void Debug_USART_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK |

DEBUG_USART_TX_GPIO_CLK,

ENABLE);

RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN ;

GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;

GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);

GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,

DEBUG_USART_RX_SOURCE,

DEBUG_USART_RX_AF);

GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,

DEBUG_USART_TX_SOURCE,

DEBUG_USART_TX_AF);

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_USART, &USART_InitStructure);

NVIC_Configuration();

USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE

USART_Cmd(DEBUG_USART, ENABLE);

}

GPIO_PinAFConfig 函数接收三个参数,第一个参数为 GPIO 端口,比如 GPIOA;第二个参数是指定要复用的引脚号,比如 GPIO_PinSource10;第三个参数是选择复用外设,比如 GPIO_AF_USART1。该函数最终操作的是 GPIO 复用功能寄存器 GPIO_AFRH 和GPIO_AFRL,分高低两个。

字符发送

void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)

{

USART_SendData(pUSARTx,ch);

while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);

}

void Usart_SendString( USART_TypeDef * pUSARTx, char *str)

{

unsigned int k=0;

do {

Usart_SendByte( pUSARTx, *(str + k) );

k++;

} while (*(str + k)!='\0');

while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {

}

}

Usart_SendByte 函数用来在指定 USART 发送一个 ASCLL 码值字符,它有两个形参,第一个为 USART,第二个为待发送的字符。它是通过调用库函数 USART_SendData 来实现的,并且增加了等待发送完成功能。通过使用 USART_GetFlagStatus 函数来获取 USART事件标志来实现发送完成功能等待,它接收两个参数,一个是 USART,一个是事件标志。这里我们循环检测发送数据寄存器为空这个标志,当跳出 while 循环时说明发送数据寄存器为空这个事实。

Usart_SendString 函数用来发送一个字符串,它实际是调用 Usart_SendByte 函数发送每个字符,直到遇到空字符才停止发送。最后使用循环检测发送完成的事件标志来实现保证数据发送完成后才退出函数

USART 中断服务函数

void DEBUG_USART_IRQHandler(void)

{

uint8_t ucTemp;

if (USART_GetITStatus(DEBUG_USART,USART_IT_RXNE)!=RESET) {

ucTemp = USART_ReceiveData( DEBUG_USART );

USART_SendData(DEBUG_USART,ucTemp);

}

}

这段代码是存放在 stm32f4xx_it.c 文件中的,该文件用来集中存放外设中断服务函数。当我们使能了中断并且中断发生时就会执行中断服务函数。

使能了 USART 接收中断,当 USART 有接收到数据就会执行DEBUG_USART_IRQHandler 函数。 USART_GetITStatus 函数与 USART_GetFlagStatus 函数类似用来获取标志位状态,但 USART_GetITStatus 函数是专门用来获取中断事件标志的,并返回该标志位状态。使用 if 语句来判断是否是真的产生 USART 数据接收这个中断事件,如果是真的就使用 USART 数据读取函数 USART_ReceiveData 读取数据到指定存储区。然后再调用 USART 数据发送函数 USART_SendData 把数据又发送给源设备。

ARM