|
本帖最后由 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);
}
}
|
-
|