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

[复制链接]
 楼主| 发表于 2015-11-10 21:47 | 显示全部楼层 |阅读模式
这个例程实现了一个菜单,然后选则S会改变USART的传输方式而M会重显菜单
以下是运行的截图:


以下是程序:
  1. #include <string.h>
  2. #include "asf.h"
  3. #include "stdio_serial.h"
  4. #include "conf_board.h"
  5. #include "conf_clock.h"
  6. #include "conf_example.h"

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

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

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

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

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

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

  19. #define STRING_EOL    "\r"
  20. #define STRING_HEADER "-- USART Serial Example --\r\n" \
  21.                 "-- "BOARD_NAME" --\r\n" \
  22.                 "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL

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

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

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

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

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

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

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

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

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

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

  43. /**
  44. * \brief Interrupt handler for USART. Echo the bytes received and start the
  45. * next receive.
  46. */
  47. void USART_Handler(void)
  48. {
  49.         uint32_t ul_status;

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

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

  57.                         /* Echo back buffer. */
  58.                         g_st_packet.ul_addr =
  59.                                         (uint32_t)gs_puc_buffer[gs_uc_buf_num];
  60.                         g_st_packet.ul_size = gs_ul_size_buffer;
  61.                         g_st_nextpacket.ul_addr =
  62.                                         (uint32_t)gs_puc_nextbuffer[gs_uc_buf_num];
  63.                         g_st_nextpacket.ul_size = gs_ul_size_nextbuffer;
  64.                         pdc_tx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);

  65.                         if (g_uc_transend_flag) {
  66.                                 gs_ul_size_buffer = BUFFER_SIZE;
  67.                                 gs_ul_size_nextbuffer = BUFFER_SIZE;
  68.                                 g_uc_transend_flag = 0;
  69.                         }

  70.                         gs_uc_buf_num = MAX_BUF_NUM - gs_uc_buf_num;

  71.                         /* Restart read on buffer. */
  72.                         g_st_packet.ul_addr =
  73.                                         (uint32_t)gs_puc_buffer[gs_uc_buf_num];
  74.                         g_st_packet.ul_size = BUFFER_SIZE;
  75.                         g_st_nextpacket.ul_addr =
  76.                                         (uint32_t)gs_puc_nextbuffer[ gs_uc_buf_num];
  77.                         g_st_nextpacket.ul_size = BUFFER_SIZE;
  78.                         pdc_rx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);

  79.                         /* Restart timer. */
  80.                         tc_start(TC0, 0);
  81.                 }
  82.         } else {
  83.                 /* Transfer without PDC. */
  84.                 if (ul_status & US_CSR_RXRDY) {
  85.                         usart_getchar(BOARD_USART, (uint32_t *)&gs_ul_read_buffer);
  86.                         usart_write(BOARD_USART, gs_ul_read_buffer);
  87.                 }
  88.         }
  89. }

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

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

  100.         /* RC compare. */
  101.         if (((ul_status & TC_SR_CPCS) == TC_SR_CPCS) &&
  102.                         (gs_uc_trans_mode == PDC_TRANSFER)) {
  103.                 /* Flush PDC buffer. */
  104.                 ul_byte_total = BUFFER_SIZE - pdc_read_rx_counter(g_p_pdc);
  105.                 if ((ul_byte_total != 0) && (ul_byte_total != BUFFER_SIZE)) {
  106.                         /* Log current size. */
  107.                         g_uc_transend_flag = 1;
  108.                         if (pdc_read_rx_next_counter(g_p_pdc) == 0) {
  109.                                 gs_ul_size_buffer = BUFFER_SIZE;
  110.                                 gs_ul_size_nextbuffer = ul_byte_total;
  111.                         } else {
  112.                                 gs_ul_size_buffer = ul_byte_total;
  113.                                 gs_ul_size_nextbuffer = 0;
  114.                         }

  115.                         /* Trigger USART Receive Buffer Full Interrupt. */
  116.                         pdc_rx_clear_cnt(g_p_pdc);
  117.                 }
  118.         }
  119. }

  120. /**
  121. * \brief Configure USART in normal (serial rs232) mode, asynchronous,
  122. * 8 bits, 1 stop bit, no parity, 115200 bauds and enable its transmitter
  123. * and receiver.
  124. */
  125. static void configure_usart(void)
  126. {
  127.         const sam_usart_opt_t usart_console_settings = {
  128.                 BOARD_USART_BAUDRATE,
  129.                 US_MR_CHRL_8_BIT,
  130.                 US_MR_PAR_NO,
  131.                 US_MR_NBSTOP_1_BIT,
  132.                 US_MR_CHMODE_NORMAL,
  133.                 /* This field is only used in IrDA mode. */
  134.                 0
  135.         };

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

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

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

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

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

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

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

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

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

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

  170. /**
  171. *  Configure UART for debug message output.
  172. */
  173. static void configure_console(void)
  174. {
  175.         const usart_serial_options_t uart_serial_options = {
  176.                 .baudrate = CONF_UART_BAUDRATE,
  177.                 .paritytype = CONF_UART_PARITY
  178.         };

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

  183. /**
  184. * \brief Reset the TX & RX, and clear the PDC counter.
  185. */
  186. static void usart_clear(void)
  187. {
  188.         /* Reset and disable receiver & transmitter. */
  189.         usart_reset_rx(BOARD_USART);
  190.         usart_reset_tx(BOARD_USART);

  191.         /* Clear PDC counter. */
  192.         g_st_packet.ul_addr = 0;
  193.         g_st_packet.ul_size = 0;
  194.         g_st_nextpacket.ul_addr = 0;
  195.         g_st_nextpacket.ul_size = 0;
  196.         pdc_rx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);

  197.         /* Enable receiver & transmitter. */
  198.         usart_enable_tx(BOARD_USART);
  199.         usart_enable_rx(BOARD_USART);
  200. }

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

  210. /**
  211. * \brief Application entry point for usart_serial example.
  212. *
  213. * \return Unused (ANSI-C compatibility).
  214. */
  215. int main(void)
  216. {
  217.         uint8_t uc_char;
  218.         uint8_t uc_flag;

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

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

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

  226.         /* Configure USART. */
  227.         configure_usart();

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

  232.         /* Configure TC. */
  233.         configure_tc();

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

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

  244.         usart_disable_interrupt(BOARD_USART, US_IDR_RXRDY);
  245.         usart_enable_interrupt(BOARD_USART, US_IER_RXBUFF);

  246.         tc_start(TC0, 0);

  247.         while (1) {
  248.                 uc_char = 0;
  249.                 uc_flag = uart_read(CONSOLE_UART, &uc_char);
  250.                 if (!uc_flag) {
  251.                         switch (uc_char) {
  252.                         case 's':
  253.                         case 'S':
  254.                                 if (gs_uc_trans_mode == PDC_TRANSFER) {
  255.                                         /* Transfer to no PDC communication mode. */
  256.                                         /* Disable PDC controller. */
  257.                                         pdc_disable_transfer(g_p_pdc,
  258.                                                         PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
  259.                                         /* Disable the RXBUFF interrupt. */
  260.                                         usart_disable_interrupt(BOARD_USART, US_IDR_RXBUFF);

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

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

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

  272.                                         /* Reset pdc current buffer size. */
  273.                                         gs_ul_size_buffer = BUFFER_SIZE;
  274.                                         gs_ul_size_nextbuffer = BUFFER_SIZE;
  275.                                         gs_uc_buf_num = 0;

  276.                                         /* Start receiving data. */
  277.                                         g_st_packet.ul_addr =
  278.                                                         (uint32_t)gs_puc_buffer[gs_uc_buf_num];
  279.                                         g_st_packet.ul_size = BUFFER_SIZE;
  280.                                         g_st_nextpacket.ul_addr =
  281.                                                         (uint32_t)gs_puc_nextbuffer[gs_uc_buf_num];
  282.                                         g_st_nextpacket.ul_size = BUFFER_SIZE;
  283.                                         pdc_rx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);
  284.                                        
  285.                                         /* Transfer to PDC communication mode, disable RXRDY interrupt and enable RXBUFF interrupt. */
  286.                                         usart_disable_interrupt(BOARD_USART, US_IER_RXRDY);
  287.                                         usart_enable_interrupt(BOARD_USART, US_IER_RXBUFF);

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

  291.                                 break;

  292.                         case 'm':
  293.                         case 'M':
  294.                                 display_main_menu();
  295.                                 break;

  296.                         default:
  297.                                 break;
  298.                         }
  299.                 }
  300.         }
  301. }

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

点评

请问关于如下问题: 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可以完整读取,请问怎么可  发表于 2024-11-29 17:42
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

2403

主题

6995

帖子

68

粉丝
快速回复 返回顶部 返回列表