返回列表 发新帖

SAM4E-EK开发板代码解读02——UART

[复制链接]

28

主题

45

帖子

1万

积分

允许发帖

积分
10186
发表于 2020-5-8 14:32:36 | 显示全部楼层 | 阅读模式
本帖最后由 Mcuzone_TKN 于 2020-5-15 09:13 编辑

关键词:Microchip Atmel SAM4E SAM4E-EK SAM4E16E芯片 UART 串口

概述:简单解读UART代码

准备工作:UART作为异步串口通信协议的一种,所以必须先要准备一根串口线,用串口线将PC的串口和开发板的串口连接在一起,同时,在PC上需要准备好串口通信软件。

串口设置:波特率115200,8位数据位,1位停止位,无奇偶校验。

从原理图得知(图1),PA10为TXD,PA9为RXD。

打开产品光盘SAM4E16E-EK/SAM4E16E-EK中文资料/softpack软件包/Atmel Studio 7,打开04a_USART0_RS485_EXAMPLE例子。

int main(void)
{
static uint8_t uc_sync = SYNC_CHAR;
uint32_t time_elapsed = 0;
uint32_t ul_i;
//初始化SAM系统
sysclk_init();
board_init()
//为调试输出配置UART
configure_console();
//输出示例信息

puts(STRING_HEADER);  
//初始化USART
configure_usart();  
//获取板USART PDC基址,并启用收发器和发射器
g_p_pdc = usart_get_pdc_base(BOARD_USART);
pdc_enable_transfer(g_p_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
//1ms滴答时钟
configure_systick();
//初始化接收缓冲区以区分发送帧
memset(g_uc_receive_buffer, 0x0, BUFFER_SIZE);
//开启发射机,要先关闭接收,避免接收
//发送字符
usart_enable_tx(BOARD_USART);
usart_disable_rx(BOARD_USART);
//发送一个同步字符XON(0x11)
g_st_packet.ul_addr = (uint32_t)&uc_sync;
g_st_packet.ul_size = 1;
pdc_tx_init(g_p_pdc, &g_st_packet, NULL);
//延迟到线路被清除 估计时间被使用
wait(50);
//阅读确认
g_st_packet.ul_addr = (uint32_t)&uc_sync;
g_st_packet.ul_size = 1;
pdc_rx_init(g_p_pdc, &g_st_packet, NULL);
//启用收发器
usart_enable_rx(BOARD_USART);
//等待超时或收到确认
time_elapsed = get_tick_count();
while (!usart_is_rx_buf_end(BOARD_USART)) {
  if (get_tick_count() - time_elapsed > TIMEOUT) {
   break;
  }
}
//如果在短时间内收到确认通知
if (usart_is_rx_buf_end(BOARD_USART)) {
  //确认
  if (uc_sync == ACK_CHAR) {
   //充当发送机 开始发送
   g_state = TRANSMITTING;
   puts("-I- Start transmitting!\r");
   g_st_packet.ul_addr = (uint32_t)g_uc_transmit_buffer;
   g_st_packet.ul_size = PDC_BUF_SIZE;
   pdc_tx_init(g_p_pdc, &g_st_packet, NULL);
   //启用传输中断
   usart_enable_interrupt(BOARD_USART, US_IER_ENDTX);
  }
} else {
  //开始接收
  g_st_packet.ul_addr = (uint32_t)&uc_sync;
  g_st_packet.ul_size = 1;
  pdc_rx_init(g_p_pdc, &g_st_packet, NULL);
  puts("-I- Receiving sync character.\r");
  while (!usart_is_rx_buf_end(BOARD_USART)) {
  }
  //收到同步字符
  if (uc_sync == SYNC_CHAR) {
   //发送XOff作为确认
   uc_sync = ACK_CHAR;
   //延时 以防字符被丢弃
   wait(100);
   //pio_set_pin_high(PIN_RE_IDX);
   g_st_packet.ul_addr = (uint32_t)&uc_sync;
   g_st_packet.ul_size = 1;
   pdc_tx_init(g_p_pdc, &g_st_packet, NULL);
   g_state = RECEIVING;
   puts("-I- Start receiving!\r");
   g_st_packet.ul_addr = (uint32_t)g_uc_receive_buffer;
   g_st_packet.ul_size = PDC_BUF_SIZE;
   pdc_rx_init(g_p_pdc, &g_st_packet, NULL);
   //pio_set_pin_low(PIN_RE_IDX);
   //启用接收中断
   usart_enable_interrupt(BOARD_USART, US_IER_ENDRX);
  }
}
while (g_state != RECEIVED) {
}
ul_i = 0;
//打印接收帧输出
while ((ul_i < BUFFER_SIZE) && (g_uc_receive_buffer[ul_i] != '\0')) {
  if (g_uc_transmit_buffer[ul_i] != g_uc_receive_buffer[ul_i]) {
   puts("-E- Error occurred while receiving!\r");
   /无限循环
   while (1) {
   }
  }
  ul_i++;
}
puts("-I- Received successfully!\r");
while (1) {
}

}



//配置USART
//异步 8位数据位 1位停止位 无奇偶校验 启用发射和接收
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,

  //此字段仅在IrDA模式下使用
  0
};
//启动PMC中的外围时钟
sysclk_enable_peripheral_clock(BOARD_ID_USART);
//在RS485模式下配置USART
usart_init_rs485(BOARD_USART, &usart_console_settings, sysclk_get_cpu_hz());
//禁用所有中断
usart_disable_interrupt(BOARD_USART, ALL_INTERRUPT_MASK);
//启用TX和RX功能
usart_enable_tx(BOARD_USART);
usart_enable_rx(BOARD_USART);

//配置和启用USART的中断
NVIC_EnableIRQ(USART_IRQn);
}



//为调试输出配置UART
static void configure_console(void)
{
const usart_serial_options_t uart_serial_options = {
  .baudrate = CONF_UART_BAUDRATE,
  .paritytype = CONF_UART_PARITY
};
//配置控制台UART
sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
stdio_serial_init(CONF_UART, &uart_serial_options);
}


//串口中断
void USART_Handler(void)
{
uint32_t ul_status;
//得到USART状态
ul_status = usart_get_status(BOARD_USART);
//接收中断
if ((ul_status & US_CSR_ENDRX) && (g_state == RECEIVING)) {
  //表示接收完成
  g_state = RECEIVED;
  usart_disable_interrupt(BOARD_USART, US_IDR_ENDRX);
}
//传输中断
else if ((ul_status & US_CSR_ENDTX) && g_state == TRANSMITTING) {
  //不断传输
  g_state = TRANSMITTED;
  usart_disable_interrupt(BOARD_USART, US_IDR_ENDTX);
}
}


图1.png
回复

使用道具 举报

359

主题

1387

帖子

5716

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5716
发表于 2020-5-13 10:21:30 | 显示全部楼层
注意,串口线是母母交叉线,交叉线。
回复 支持 反对

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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