打印
[Atmel]

用SAM-BA或JLINK跑ATSAM4E16的程序(8)USART例程

[复制链接]
2450|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ddllxxrr|  楼主 | 2015-11-10 21:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
这个例程实现了一个菜单,然后选则S会改变USART的传输方式而M会重显菜单
以下是运行的截图:


以下是程序:
#include <string.h>
#include "asf.h"
#include "stdio_serial.h"
#include "conf_board.h"
#include "conf_clock.h"
#include "conf_example.h"

/** Size of the receive buffer used by the PDC, in bytes. */
#define BUFFER_SIZE         100

/** USART PDC transfer type definition. */
#define PDC_TRANSFER        1

/** USART FIFO transfer type definition. */
#define BYTE_TRANSFER       0

/** Max buffer number. */
#define MAX_BUF_NUM         1

/** All interrupt mask. */
#define ALL_INTERRUPT_MASK  0xffffffff

/** Timer counter frequency in Hz. */
#define TC_FREQ             1

#define STRING_EOL    "\r"
#define STRING_HEADER "-- USART Serial Example --\r\n" \
                "-- "BOARD_NAME" --\r\n" \
                "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL

/** Receive buffer. */
static uint8_t gs_puc_buffer[2][BUFFER_SIZE];

/** Next Receive buffer. */
static uint8_t gs_puc_nextbuffer[2][BUFFER_SIZE];

/** Current bytes in buffer. */
static uint32_t gs_ul_size_buffer = BUFFER_SIZE;

/** Current bytes in next buffer. */
static uint32_t gs_ul_size_nextbuffer = BUFFER_SIZE;

/** Byte mode read buffer. */
static uint32_t gs_ul_read_buffer = 0;

/** Current transfer mode. */
static uint8_t gs_uc_trans_mode = PDC_TRANSFER;

/** Buffer number in use. */
static uint8_t gs_uc_buf_num = 0;

/** PDC data packet. */
pdc_packet_t g_st_packet, g_st_nextpacket;

/** Pointer to PDC register base. */
Pdc *g_p_pdc;

/** Flag of one transfer end. */
static uint8_t g_uc_transend_flag = 0;

/**
* \brief Interrupt handler for USART. Echo the bytes received and start the
* next receive.
*/
void USART_Handler(void)
{
        uint32_t ul_status;

        /* Read USART Status. */
        ul_status = usart_get_status(BOARD_USART);

        if (gs_uc_trans_mode == PDC_TRANSFER) {
                /* Receive buffer is full. */
                if (ul_status & US_CSR_RXBUFF) {
                        /* Disable timer. */
                        tc_stop(TC0, 0);

                        /* Echo back buffer. */
                        g_st_packet.ul_addr =
                                        (uint32_t)gs_puc_buffer[gs_uc_buf_num];
                        g_st_packet.ul_size = gs_ul_size_buffer;
                        g_st_nextpacket.ul_addr =
                                        (uint32_t)gs_puc_nextbuffer[gs_uc_buf_num];
                        g_st_nextpacket.ul_size = gs_ul_size_nextbuffer;
                        pdc_tx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);

                        if (g_uc_transend_flag) {
                                gs_ul_size_buffer = BUFFER_SIZE;
                                gs_ul_size_nextbuffer = BUFFER_SIZE;
                                g_uc_transend_flag = 0;
                        }

                        gs_uc_buf_num = MAX_BUF_NUM - gs_uc_buf_num;

                        /* Restart read on buffer. */
                        g_st_packet.ul_addr =
                                        (uint32_t)gs_puc_buffer[gs_uc_buf_num];
                        g_st_packet.ul_size = BUFFER_SIZE;
                        g_st_nextpacket.ul_addr =
                                        (uint32_t)gs_puc_nextbuffer[ gs_uc_buf_num];
                        g_st_nextpacket.ul_size = BUFFER_SIZE;
                        pdc_rx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);

                        /* Restart timer. */
                        tc_start(TC0, 0);
                }
        } else {
                /* Transfer without PDC. */
                if (ul_status & US_CSR_RXRDY) {
                        usart_getchar(BOARD_USART, (uint32_t *)&gs_ul_read_buffer);
                        usart_write(BOARD_USART, gs_ul_read_buffer);
                }
        }
}

/**
* \brief Interrupt handler for TC0. Record the number of bytes received,
* and then restart a read transfer on the USART if the transfer was stopped.
*/
void TC0_Handler(void)
{
        uint32_t ul_status;
        uint32_t ul_byte_total = 0;

        /* Read TC0 Status. */
        ul_status = tc_get_status(TC0, 0);

        /* RC compare. */
        if (((ul_status & TC_SR_CPCS) == TC_SR_CPCS) &&
                        (gs_uc_trans_mode == PDC_TRANSFER)) {
                /* Flush PDC buffer. */
                ul_byte_total = BUFFER_SIZE - pdc_read_rx_counter(g_p_pdc);
                if ((ul_byte_total != 0) && (ul_byte_total != BUFFER_SIZE)) {
                        /* Log current size. */
                        g_uc_transend_flag = 1;
                        if (pdc_read_rx_next_counter(g_p_pdc) == 0) {
                                gs_ul_size_buffer = BUFFER_SIZE;
                                gs_ul_size_nextbuffer = ul_byte_total;
                        } else {
                                gs_ul_size_buffer = ul_byte_total;
                                gs_ul_size_nextbuffer = 0;
                        }

                        /* Trigger USART Receive Buffer Full Interrupt. */
                        pdc_rx_clear_cnt(g_p_pdc);
                }
        }
}

/**
* \brief Configure USART in normal (serial rs232) mode, asynchronous,
* 8 bits, 1 stop bit, no parity, 115200 bauds and enable its transmitter
* and receiver.
*/
static void configure_usart(void)
{
        const sam_usart_opt_t usart_console_settings = {
                BOARD_USART_BAUDRATE,
                US_MR_CHRL_8_BIT,
                US_MR_PAR_NO,
                US_MR_NBSTOP_1_BIT,
                US_MR_CHMODE_NORMAL,
                /* This field is only used in IrDA mode. */
                0
        };

        /* Enable the peripheral clock in the PMC. */
        sysclk_enable_peripheral_clock(BOARD_ID_USART);

        /* Configure USART in serial mode. */
        usart_init_rs232(BOARD_USART, &usart_console_settings,
                        sysclk_get_cpu_hz());

        /* Disable all the interrupts. */
        usart_disable_interrupt(BOARD_USART, ALL_INTERRUPT_MASK);

        /* Enable the receiver and transmitter. */
        usart_enable_tx(BOARD_USART);
        usart_enable_rx(BOARD_USART);

        /* Configure and enable interrupt of USART. */
        NVIC_EnableIRQ(USART_IRQn);
}

/**
* \brief Configure Timer Counter 0 (TC0) to generate an interrupt every 200ms.
* This interrupt will be used to flush USART input and echo back.
*/
static void configure_tc(void)
{
        uint32_t ul_div;
        uint32_t ul_tcclks;
        static uint32_t ul_sysclk;

        /* Get system clock. */
        ul_sysclk = sysclk_get_cpu_hz();

        /* Configure PMC. */
        pmc_enable_periph_clk(ID_TC0);

        /* Configure TC for a 50Hz frequency and trigger on RC compare. */
        tc_find_mck_divisor(TC_FREQ, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk);
        tc_init(TC0, 0, ul_tcclks | TC_CMR_CPCTRG);
        tc_write_rc(TC0, 0, (ul_sysclk / ul_div) / TC_FREQ);

        /* Configure and enable interrupt on RC compare. */
        NVIC_EnableIRQ((IRQn_Type)ID_TC0);
        tc_enable_interrupt(TC0, 0, TC_IER_CPCS);
}

/**
*  Configure UART for debug message output.
*/
static void configure_console(void)
{
        const usart_serial_options_t uart_serial_options = {
                .baudrate = CONF_UART_BAUDRATE,
                .paritytype = CONF_UART_PARITY
        };

        /* Configure console UART. */
        sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
        stdio_serial_init(CONF_UART, &uart_serial_options);
}

/**
* \brief Reset the TX & RX, and clear the PDC counter.
*/
static void usart_clear(void)
{
        /* Reset and disable receiver & transmitter. */
        usart_reset_rx(BOARD_USART);
        usart_reset_tx(BOARD_USART);

        /* Clear PDC counter. */
        g_st_packet.ul_addr = 0;
        g_st_packet.ul_size = 0;
        g_st_nextpacket.ul_addr = 0;
        g_st_nextpacket.ul_size = 0;
        pdc_rx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);

        /* Enable receiver & transmitter. */
        usart_enable_tx(BOARD_USART);
        usart_enable_rx(BOARD_USART);
}

/**
* \brief Display main menu.
*/
static void display_main_menu(void)
{
        puts("-- Menu Choices for this example --\r\n"
                        "-- s: Switch mode for USART between PDC and without PDC.--\r\n"
                        "-- m: Display this menu again.--\r");
}

/**
* \brief Application entry point for usart_serial example.
*
* \return Unused (ANSI-C compatibility).
*/
int main(void)
{
        uint8_t uc_char;
        uint8_t uc_flag;

        /* Initialize the SAM system. */
        sysclk_init();
        board_init();

        /* Configure UART for debug message output. */
        configure_console();

        /* Output example information. */
        puts(STRING_HEADER);

        /* Configure USART. */
        configure_usart();

        /* Get board USART PDC base address. */
        g_p_pdc = usart_get_pdc_base(BOARD_USART);
        /* Enable receiver and transmitter. */
        pdc_enable_transfer(g_p_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

        /* Configure TC. */
        configure_tc();

        /* Start receiving data and start timer. */
        g_st_packet.ul_addr = (uint32_t)gs_puc_buffer[gs_uc_buf_num];
        g_st_packet.ul_size = BUFFER_SIZE;
        g_st_nextpacket.ul_addr = (uint32_t)gs_puc_nextbuffer[gs_uc_buf_num];
        g_st_nextpacket.ul_size = BUFFER_SIZE;
        pdc_rx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);

        puts("-- Start to echo serial inputs -- \r\n"
                        "-I- Default Transfer with PDC \r\n"
                        "-I- Press 's' to switch transfer mode \r");
        gs_uc_trans_mode = PDC_TRANSFER;

        usart_disable_interrupt(BOARD_USART, US_IDR_RXRDY);
        usart_enable_interrupt(BOARD_USART, US_IER_RXBUFF);

        tc_start(TC0, 0);

        while (1) {
                uc_char = 0;
                uc_flag = uart_read(CONSOLE_UART, &uc_char);
                if (!uc_flag) {
                        switch (uc_char) {
                        case 's':
                        case 'S':
                                if (gs_uc_trans_mode == PDC_TRANSFER) {
                                        /* Transfer to no PDC communication mode. */
                                        /* Disable PDC controller. */
                                        pdc_disable_transfer(g_p_pdc,
                                                        PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
                                        /* Disable the RXBUFF interrupt. */
                                        usart_disable_interrupt(BOARD_USART, US_IDR_RXBUFF);

                                        /* Clear USART controller. */
                                        usart_clear();

                                        /* Enable the RXRDY interrupt. */
                                        usart_enable_interrupt(BOARD_USART, US_IER_RXRDY);
                                        gs_uc_trans_mode = BYTE_TRANSFER;

                                        puts("-I- Transfer without PDC \r");
                                } else if (gs_uc_trans_mode == BYTE_TRANSFER) {
                                        pdc_enable_transfer(g_p_pdc,
                                                        PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
                                        /* Clear USART controller. */
                                        usart_clear();

                                        /* Reset pdc current buffer size. */
                                        gs_ul_size_buffer = BUFFER_SIZE;
                                        gs_ul_size_nextbuffer = BUFFER_SIZE;
                                        gs_uc_buf_num = 0;

                                        /* Start receiving data. */
                                        g_st_packet.ul_addr =
                                                        (uint32_t)gs_puc_buffer[gs_uc_buf_num];
                                        g_st_packet.ul_size = BUFFER_SIZE;
                                        g_st_nextpacket.ul_addr =
                                                        (uint32_t)gs_puc_nextbuffer[gs_uc_buf_num];
                                        g_st_nextpacket.ul_size = BUFFER_SIZE;
                                        pdc_rx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);
                                       
                                        /* Transfer to PDC communication mode, disable RXRDY interrupt and enable RXBUFF interrupt. */
                                        usart_disable_interrupt(BOARD_USART, US_IER_RXRDY);
                                        usart_enable_interrupt(BOARD_USART, US_IER_RXBUFF);

                                        gs_uc_trans_mode = PDC_TRANSFER;
                                        puts("-I- Transfer with PDC \r");
                                }

                                break;

                        case 'm':
                        case 'M':
                                display_main_menu();
                                break;

                        default:
                                break;
                        }
                }
        }
}

至于例程的解析明天再发表。

评论
xuxunfighting 2024-11-29 17:42 回复TA
请问关于如下问题: if (ul_status & US_CSR_RXRDY) { usart_getchar(BOARD_USART, (uint32_t *)&gs_ul_read_buffer); usart_write(BOARD_USART, gs_ul_read_buffer); } 采用这个方式进行串口的读写,发现在一次性接收很多字节数据时,出现usart_write发送丢包现象,检查之后usart_getchar可以完整读取,请问怎么可以保证读写字节一致呢? 

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:http://shop34182318.taobao.com/ http://shop562064536.taobao.com

2399

主题

6964

帖子

68

粉丝