This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
串口发送很简单,但是处理不好就会遇到问题,这次我用官方提供的回显的例子进行测试。发现了要注意事项。
void EUSCIA0_IRQHandler(void) { if (EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG) { // Check if the TX buffer is empty first while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); // Echo the received character back EUSCI_A0->TXBUF = EUSCI_A0->RXBUF; } }
这是官方例子中处理回显的,我们可以看到在将本次接收的字符发送回去时候,进行了一个判断,这个判断实际上是判断是不是发送缓冲器里面的内容是不是已经发送完了,再进行
新的发送。如果不加这个会怎么样呢?
我经过测试,添加了若干的发送内容后发现,不加这个,还真不行,会导致接收混乱,你还没有发送出去的数据会被覆盖掉。
// UART interrupt service routine void EUSCIA0_IRQHandler(void) { if (EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG) { // Check if the TX buffer is empty first while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); EUSCI_A0->TXBUF=i+'0'; // while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); EUSCI_A0->TXBUF=':'; // while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); i++; // Echo the received character back EUSCI_A0->TXBUF = EUSCI_A0->RXBUF; // EUSCI_A0->TXBUF='\n'; } }
void EUSCIA0_IRQHandler(void) { if (EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG) { // Check if the TX buffer is empty first while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); EUSCI_A0->TXBUF=i+'0'; while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); EUSCI_A0->TXBUF=':'; // while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); i++; // Echo the received character back while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); EUSCI_A0->TXBUF = EUSCI_A0->RXBUF; while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG)); EUSCI_A0->TXBUF='\n'; } }
现在我对每次发送的内容都进行一次缓冲器忙的检测等待。这样效果就不同了。
要实现printf,就需要重写两个函数:
int fputc(int _c, register FILE *_fp)
int fputs(const char *_ptr, register FILE *_fp)
-----------------------------------------------
int fputc(int _c, register FILE *_fp) { MAP_UART_transmitData( DEBUG_UART_MODULE , (uint8_t) _c); while (!MAP_UART_getInterruptStatus(DEBUG_UART_MODULE, EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG)); EUSCI_A_CMSIS(DEBUG_UART_MODULE)->IFG |= (EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG); return _c; } int fputs(const char *_ptr, register FILE *_fp) { uint16_t i, len; len = strlen(_ptr); for(i=0; i<len; i++) { MAP_UART_transmitData( DEBUG_UART_MODULE , (unsigned char)_ptr[i] ); while (!MAP_UART_getInterruptStatus(DEBUG_UART_MODULE, EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG)); EUSCI_A_CMSIS(DEBUG_UART_MODULE)->IFG |= (EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG); } return len; }
另外就是还可以采用基于库函数的操作方式。比如回显就是
/* * ------------------------------------------- * MSP432 DriverLib - v3_21_00_05 * ------------------------------------------- * * --COPYRIGHT--,BSD,BSD * Copyright (c) 2016, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ /****************************************************************************** * MSP432 UART - PC Echo with 12MHz BRCLK * * Description: This demo echoes back characters received via a PC serial port. * SMCLK/DCO is used as a clock source and the device is put in LPM0 * The auto-clock enable feature is used by the eUSCI and SMCLK is turned off * when the UART is idle and turned on when a receive edge is detected. * Note that level shifter hardware is needed to shift between RS232 and MSP * voltage levels. * * MSP432P401 * ----------------- * | | * | | * | | * RST -| P1.3/UCA0TXD|----> PC (echo) * | | * | | * | P1.2/UCA0RXD|<---- PC * | | * * Author: Timothy Logan *******************************************************************************/ /* DriverLib Includes */ #include "driverlib.h" /* Standard Includes */ #include <stdint.h> #include <stdbool.h> /* UART Configuration Parameter. These are the configuration parameters to * make the eUSCI A UART module to operate with a 9600 baud rate. These * values were calculated using the online calculator that TI provides * at: *software-dl.ti.com/.../index.html */ const eUSCI_UART_Config uartConfig = { EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 78, // BRDIV = 78 2, // UCxBRF = 2 0, // UCxBRS = 0 EUSCI_A_UART_NO_PARITY, // No Parity EUSCI_A_UART_LSB_FIRST, // LSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION // Oversampling }; int main(void) { /* Halting WDT */ MAP_WDT_A_holdTimer(); /* Selecting P1.2 and P1.3 in UART mode */ MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION); /* Setting DCO to 12MHz */ CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12); /* Configuring UART Module */ MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig); /* Enable UART module */ MAP_UART_enableModule(EUSCI_A0_BASE); /* Enabling interrupts */ MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); MAP_Interrupt_enableInterrupt(INT_EUSCIA0); MAP_Interrupt_enableSleepOnIsrExit(); MAP_Interrupt_enableMaster(); while(1) { MAP_PCM_gotoLPM0(); } } /* EUSCI A0 UART ISR - Echoes data back to PC host */ void EUSCIA0_IRQHandler(void) { uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status); if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) { MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE)); } }