关于APM32F103单片机串口发送问题

这里出现该问题主要是我有时需要串口发送脚,切换为普通IO口中断来使用。
前篇提要

之前文章中有提过GD32串口发送丢失字节的问题,使用的轮询标志位,发送使用了while等待,造成了数据丢失,因为该单片机硬件自行处理了“发送缓冲区空标志”和“发送完成标志”;不需要程序去做多余的等待。

这里Geehy(极海)的32单片机用户手册上给出来的和GD32处理不一样。

上诉大概意思和发送的步骤如下:

 -->当发送寄存器为空(数据寄存器(USART_DATA))=TXBEF=1时

-->数据写入USART_DATA寄存器,自动TXBEF=0

-->数据会自行移入  移位寄存器 中;(移入完成后,DATA为空,TXBEF=1,此时又可以写入数据了)

-->移位寄存器中有数据后,TX开始发送数据;(当发送完成,且TXBEF=1; 才会硬件置位发送完成标志TXCF=1)

最后一步可以说是,你发送一个数组,当最后一个字节发送完成时,就可以查询txcf标志,看发送完成没。

void USART_Init(USART_T* usart)
{
    USART_Config_T usartConfig;

    /*  BaudRate is 9600 */
    usartConfig.baudRate = 9600;
    /*  No interrupt */
    usartConfig.interrupt = USART_INT_NONE;
    /* Enable receive and transmit */
    usartConfig.mode = USART_MODE_TX;//只使能了TX
    /*  Parity disable */
    usartConfig.parity = USART_PARITY_NONE;
    /*  One stop bit */
    usartConfig.stopBits = USART_STOP_BIT_1;
    /*  Word length is 8bit */
    usartConfig.wordLength = USART_WORD_LEN_8B;
    /*  USART1 configuration */
    USART_Config(USART1, &usartConfig);
    /*  Enable USART1 */
    USART_Enable(USART1);
}

/**************************************************************************************
函数名称:USARTX_Send
功    能:发送一组数据
参    数:pary,待发送数组首地址
		  len,待发送数据长度
返 回 值:无
**************************************************************************************/
void USARTX_Send(USART_T* usart, char data)
{
      /* Wait until end of transmission */
			while(USART_ReadStatusFlag(usart, USART_FLAG_TXBE) == RESET){};//等待DATA数据寄存器为空TXBEF=1;
      
      USART_TxData8(usart, data);//这里是将数据写入DATA数据寄存器 TXBEF=0
	
}


// 主函数
int main(void)
{
  USART_Init(USART1);
	
  while (1)
  {
		USART_COM_Init_TX();//切换为USART1_TX
		for(i=0; i<6; i++)
		USARTX_Send(USART1,send_card[i]);//发送一串数据
        
        while(USART_ReadStatusFlag(USART1, USART_FLAG_TXC) == RESET);//这里是等待数据发送成,和TXBEF=1; 发送完成标志才会置1,TXCF=1

        /*这里需要等待上面数组发送完成,才能切换,否则会丢失数据*/
		USART_COM_Init_RX();//切换为普通IO口,下降沿中断
  }
}

下面代码是通过中断来发送数据

void USART_Init(USART_T* usart)
{
    USART_Config_T usartConfig;

    /*  BaudRate is 9600 */
    usartConfig.baudRate = 9600;
    /*  No interrupt */
    usartConfig.interrupt = USART_INT_TX;//发送缓冲区空中断, TXBEF 置位时,产生中断 
    /* Enable receive and transmit */
    usartConfig.mode = USART_MODE_TX;//只使能了TX
    /*  Parity disable */
    usartConfig.parity = USART_PARITY_NONE;
    /*  One stop bit */
    usartConfig.stopBits = USART_STOP_BIT_1;
    /*  Word length is 8bit */
    usartConfig.wordLength = USART_WORD_LEN_8B;
    /*  USART1 configuration */
    USART_Config(USART1, &usartConfig);
    /*  Enable USART1 */
    USART_Enable(USART1);
	
	/*  Enable USART1 transmitter IRQ request */
    NVIC_EnableIRQRequest(USART1_TX_IRQn, 0x01);
}

/*!
 * @brief       USART1 transmitter interrupt service routine
 *
 * @param       None
 *
 * @retval      None
 */
uint8_t tx1DataPt = 0;
extern unsigned char send_card[6];
void USART1_TxIsr(void)
{
    if(USART_ReadIntFlag(USART1, USART_INT_FLAG_TX) == SET)
    {
        if(tx1DataPt < 6)
        {
            USART_TxData8(USART1, send_card[tx1DataPt++]);
        }
        else
        {
            tx1DataPt=0;
			/* Disable USART1 transmitter interrupt */
            USART_DisableInterrupt(USART1, USART_INT_TX);
        }
    }
}

/*!
 * @brief       This function handles USART1 receiver exception
 *
 * @param       None
 *
 * @retval      None
 */
void USART1_TX_IRQHandler(void)
{
    USART1_TxIsr();
}


// 主函数
extern uint8_t tx1DataPt;
int main(void)
{
  USART_Init(USART1);
	
  while (1)
  {
		USART_COM_Init_TX();//切换为USART1_TX
		
        
        while(USART_ReadStatusFlag(USART1, USART_FLAG_TXC) == RESET);//这里是等待数据发送成,和TXBEF=1; 发送完成标志才会置1,TXCF=1
        /*也可以使用下面代码替代上面的while循环*/
//        while(txDataPt < 6);//6是数组的大小

        /*这里需要等待上面数组发送完成,才能切换,否则会丢失数据*/
		USART_COM_Init_RX();//切换为普通IO口,下降沿中断
  }
}

以下是串口和普通IO口相互切换的代码
 

/*!
 * @brief       USART_COM_Init_RX,  Initialize to a common I/O port
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
void USART_COM_Init_RX(void)
{
	USART_Reset(USART1);//失能USART1
	
	GPIO_Config_T gpioConfig;
	
	gpioConfig.mode = GPIO_MODE_IN_PU;
    gpioConfig.speed = GPIO_SPEED_10MHz;
    gpioConfig.intEn = GPIO_EINT_ENABLE;
	gpioConfig.pin = GPIO_PIN_5;
	GPIO_Config(GPIOD, &gpioConfig);
	
	GPIO_SetBit(GPIOD, GPIO_PIN_5);
	
	EINT_Config(EINT_PORT_D, EINT_TRIGGER_FALLING);
    NVIC_EnableIRQRequest(EINTD_IRQn, 0X0f);

}


/*!
 * @brief       Initialize to USART1
 *
 * @param       None
 *
 * @retval      None
 *
 * @note
 */
void USART_COM_Init_TX(void)
{
	Disable_EINT_D();//将PD5的中断失能
	USART_Init(USART1);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值