Почему, когда я шлю в микроконтроллер символ "1" - это отправление обратабывается с первого раза, при этом, если я шлю символ "2", нужно 2 раза передать с компьютера цифру, и т.д.?
Программу main.c и usart.c прилагаю.
main.c:
Код: Выделить всё
#include "AT91SAM7X256.h"
#include <usart/usart.h>
int main(void) {
int i;
//*******************Начальная инициализация*************************************
//*******************Инициализация PMC*******************************************
//*******************Синхронизация***********************************************
//*******************Источник синхронизации: основной генератор; предделитель 1**
volatile AT91PS_CKGR pCKGR = AT91C_BASE_CKGR;
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
pCKGR->CKGR_MOR = 0x00000701; // Включение основного генератора
while((pPMC->PMC_SR & (0x1<<0))==0); // Ожидание установки бита MOSCS
pCKGR->CKGR_PLLR = 0x00013F02;
while((pPMC->PMC_SR & (0x1<<2))==0);
pPMC->PMC_MCKR = 0x00000003; // Выбор источника синхронизации и установка предделителя
while((pPMC->PMC_SR & (0x1<<3))==0); // Ожидание установки бита MCKRDY
//***********************************************************************************
pPMC->PMC_PCER = 0x44;
//***********************************************************************************
// конфигурирование PIO
volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA; // pointer to PIO data structure
pPIOA->PIO_PDR = 0x00000003;
pPIOA->PIO_ASR = 0x00000003;
pPIOA->PIO_PER = (1<<2) | (1<<27) | (1<<28) | (1<<29);
pPIOA->PIO_PPUDR = 0x38E00017; // сбрасываем подтягивающий резистор для led и RxD0 и TxD0
pPIOA->PIO_OER = (1<<2) | (1<<27) | (1<<28) | (1<<29); // разрешение выхода
pPIOA->PIO_CODR = (1<<2) | (1<<27) | (1<<28) | (1<<29);
// работа с usart0
AT91S_USART *usart = AT91C_BASE_US0;
USART_Configure(usart, USART_MODE_ASYNCHRONOUS, 38400, 18432000); // Настройка USART0
USART_SetReceiverEnabled(usart, 1);
while(1) {
if ((USART_Read(usart, 0))=='1')
{
pPIOA->PIO_SODR = (1<<2);
}
else if ((USART_Read(usart, 0))=='2')
{
pPIOA->PIO_SODR = (1<<29);
}
else if ((USART_Read(usart, 0))=='3')
{
pPIOA->PIO_SODR = (1<<28);
}
else if ((USART_Read(usart, 0))=='4')
{
pPIOA->PIO_SODR = (1<<27);
}
else
{
pPIOA->PIO_CODR = (1<<2) | (1<<27) | (1<<28) | (1<<29);
}
}
while(1);
}Код: Выделить всё
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* 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 disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "usart.h"
#include "trace.h"
#include "assert.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures an USART peripheral with the specified parameters.
/// \param usart Pointer to the USART peripheral to configure.
/// \param mode Desired value for the USART mode register (see the datasheet).
/// \param baudrate Baudrate at which the USART should operate (in Hz).
/// \param masterClock Frequency of the system master clock (in Hz).
//------------------------------------------------------------------------------
void USART_Configure(AT91S_USART *usart,
unsigned int mode,
unsigned int baudrate,
unsigned int masterClock)
{
// Reset and disable receiver & transmitter
usart->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX
| AT91C_US_RXDIS | AT91C_US_TXDIS;
// Configure mode
usart->US_MR = mode;
// Configure baudrate
// Asynchronous, no oversampling
if (((mode & AT91C_US_SYNC) == 0)
&& ((mode & AT91C_US_OVER) == 0)) {
usart->US_BRGR = (masterClock / baudrate) / 16;
}
// TODO other modes
}
//------------------------------------------------------------------------------
/// Enables or disables the transmitter of an USART peripheral.
/// \param usart Pointer to an USART peripheral
/// \param enabled If true, the transmitter is enabled; otherwise it is
/// disabled.
//------------------------------------------------------------------------------
void USART_SetTransmitterEnabled(AT91S_USART *usart,
unsigned char enabled)
{
if (enabled) {
usart->US_CR = AT91C_US_TXEN;
}
else {
usart->US_CR = AT91C_US_TXDIS;
}
}
//------------------------------------------------------------------------------
/// Enables or disables the receiver of an USART peripheral
/// \param usart Pointer to an USART peripheral
/// \param enabled If true, the receiver is enabled; otherwise it is disabled.
//------------------------------------------------------------------------------
void USART_SetReceiverEnabled(AT91S_USART *usart,
unsigned char enabled)
{
if (enabled) {
usart->US_CR = AT91C_US_RXEN;
}
else {
usart->US_CR = AT91C_US_RXDIS;
}
}
//------------------------------------------------------------------------------
/// Sends one packet of data through the specified USART peripheral. This
/// function operates synchronously, so it only returns when the data has been
/// actually sent.
/// \param usart Pointer to an USART peripheral.
/// \param data Data to send including 9nth bit and sync field if necessary (in
/// the same format as the US_THR register in the datasheet).
/// \param timeOut Time out value (0 = no timeout).
//------------------------------------------------------------------------------
void USART_Write(
AT91S_USART *usart,
unsigned short data,
volatile unsigned int timeOut)
{
if (timeOut == 0) {
while ((usart->US_CSR & AT91C_US_TXEMPTY) == 0);
}
else {
while ((usart->US_CSR & AT91C_US_TXEMPTY) == 0) {
if (timeOut == 0) {
TRACE_ERROR("USART_Write: Timed out.\n\r");
return;
}
timeOut--;
}
}
usart->US_THR = data;
}
//------------------------------------------------------------------------------
/// Sends the contents of a data buffer through the specified USART peripheral.
/// This function returns immediately (1 if the buffer has been queued, 0
/// otherwise); poll the ENDTX and TXBUFE bits of the USART status register
/// to check for the transfer completion.
/// \param usart Pointer to an USART peripheral.
/// \param buffer Pointer to the data buffer to send.
/// \param size Size of the data buffer (in bytes).
//------------------------------------------------------------------------------
unsigned char USART_WriteBuffer(
AT91S_USART *usart,
void *buffer,
unsigned int size)
{
// Check if the first PDC bank is free
if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
usart->US_TPR = (unsigned int) buffer;
usart->US_TCR = size;
usart->US_PTCR = AT91C_PDC_TXTEN;
return 1;
}
// Check if the second PDC bank is free
else if (usart->US_TNCR == 0) {
usart->US_TNPR = (unsigned int) buffer;
usart->US_TNCR = size;
return 1;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Reads and return a packet of data on the specified USART peripheral. This
/// function operates asynchronously, so it waits until some data has been
/// received.
/// \param usart Pointer to an USART peripheral.
/// \param timeOut Time out value (0 -> no timeout).
//------------------------------------------------------------------------------
unsigned short USART_Read(
AT91S_USART *usart,
volatile unsigned int timeOut)
{
if (timeOut == 0) {
while ((usart->US_CSR & AT91C_US_RXRDY) == 0);
}
else {
while ((usart->US_CSR & AT91C_US_RXRDY) == 0) {
if (timeOut == 0) {
TRACE_ERROR("USART_Read: Timed out.\n\r");
return 0;
}
timeOut--;
}
}
return usart->US_RHR;
}
//------------------------------------------------------------------------------
/// Reads data from an USART peripheral, filling the provided buffer until it
/// becomes full. This function returns immediately with 1 if the buffer has
/// been queued for transmission; otherwise 0.
/// \param usart Pointer to an USART peripheral.
/// \param buffer Pointer to the buffer where the received data will be stored.
/// \param size Size of the data buffer (in bytes).
//------------------------------------------------------------------------------
unsigned char USART_ReadBuffer(AT91S_USART *usart,
void *buffer,
unsigned int size)
{
// Check if the first PDC bank is free
if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) {
usart->US_RPR = (unsigned int) buffer;
usart->US_RCR = size;
usart->US_PTCR = AT91C_PDC_RXTEN;
return 1;
}
// Check if the second PDC bank is free
else if (usart->US_RNCR == 0) {
usart->US_RNPR = (unsigned int) buffer;
usart->US_RNCR = size;
return 1;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Returns 1 if some data has been received and can be read from an USART;
/// otherwise returns 0.
/// \param usart Pointer to an AT91S_USART instance.
//------------------------------------------------------------------------------
unsigned char USART_IsDataAvailable(AT91S_USART *usart)
{
if ((usart->US_CSR & AT91C_US_RXRDY) != 0) {
return 1;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Sets the filter value for the IRDA demodulator.
/// \param pUsart Pointer to an AT91S_USART instance.
/// \param filter Filter value.
//------------------------------------------------------------------------------
void USART_SetIrdaFilter(AT91S_USART *pUsart, unsigned char filter)
{
SANITY_CHECK(pUsart);
pUsart->US_IF = filter;
}
