一、准备工作: 将上一节搭建的工程复制一份,命名为“4.usart”。这一节主要讲如何使用SAM4N的USART功能,实现串口的收发。 二、程序编写: SAM4N除了4个UART,还提供了3个USART,这3个USART可以配置成多种模式,支持SPI模式,流控模式,IrDA红外模式,IS07816模式,RS485模式等,真的很强大,足以满足用户连接各种Modem,射频卡等需求。 file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps_clip_image-9224.png
通过上面这段概述可以知道,USART比上一节的UART要多了不少功能。 file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps_clip_image-19684.png
由上面的表格可以看出PA5和PA6分别为USART0的RXD和TXD,都是用的是外设功能A,和上一节讲的UART0很类似。 file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps_clip_image-13301.png
从上面的描述可以看出,计算波特率的方式和UART有些不同。 总体上来看,USART和UART有很多相似的地方,委员不同的是波特率的配置和模式配置,多了很多模式。 下面开始编写USART0的初始化代码。 /************************************************************* * 函数名:USART0_Init() * 参数 :uint32_t buadrate 波特率 * 返回值:void * 描述 :USART0初始化函数,在使用USART0前先调用 *************************************************************/ void USART0_Init(uint32_t baudrate) { /*禁止外设管理控制寄存器(PMC)写保护*/ PMC->PMC_WPMR = 0x504D4300; /*使能USART1和PIOA时钟*/ PMC->PMC_PCER0 = ((1UL << ID_PIOA) | (1UL << ID_USART0) ); /*使能外设管理控制寄存器(PMC)写保护*/ PMC->PMC_WPMR = 0x504D4301; /*配置PA5为USART0的RXD,PA6为USART0的TXD*/ PIOA->PIO_IDR=(PIO_PA5A_RXD0|PIO_PA6A_TXD0); PIOA->PIO_PUDR=(PIO_PA5A_RXD0|PIO_PA6A_TXD0); PIOA->PIO_ABCDSR[0]&=~(PIO_PA5A_RXD0|PIO_PA6A_TXD0); PIOA->PIO_ABCDSR[1]&=~(PIO_PA5A_RXD0|PIO_PA6A_TXD0); PIOA->PIO_PDR=(PIO_PA5A_RXD0|PIO_PA6A_TXD0); /* 复位并禁止USART的发送和接收*/ USART0->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS; /*配置USART0的波特率*/ USART0->US_BRGR=BAUD(baudrate); /*定义数据位为8bit,停止位为1,校验位为NONE*/ USART0->US_MR = US_MR_USART_MODE_NORMAL| //普通模式 US_MR_CHRL_8_BIT| //数据位为8位 US_MR_NBSTOP_1_BIT| //停止位为1位 US_MR_PAR_NO| //校验位为NONE US_MR_CHMODE_NORMAL; //普通通道模式 /*禁止 DMA 通道 */ USART0->US_PTCR = US_PTCR_RXTDIS | US_PTCR_TXTDIS; /*使能USART接收和发送*/ USART0->US_CR = US_CR_RXEN | US_CR_TXEN; /*使能接收中断*/ USART0->US_IER=US_IER_RXRDY; /*配置USART0的先占优先级为1,从优先级为1*/ NVIC_SetPriority(USART0_IRQn, ((0x01<<3)|0x01)); /*使能USART0的中断通道*/ NVIC_EnableIRQ(USART0_IRQn); } 从代码上来看,和UART的配置一样,就是寄存器的名字变了一点,模式配置那里多了数据位,停止位的配置,其他基本就是一样的。 下面是接收和发送代码: /************************************************************* * 函数名:USART0_Handler() * 参数 :void * 返回值:void * 描述 :USART0中断服务函数 *************************************************************/ void USART0_Handler(void) { uint8_t temp; if((USART0->US_CSR& US_CSR_RXRDY)==1) { //接收数据中断 temp= USART0->US_RHR&0xff; //接收一个字节 USART0_SendByte(temp); //将接收的数据发回 } } /*************************************************************** * 函数名:USART0_SendByte() * 参数 :uint8_t c 要发送字符 * 返回值:void * 描述 :USART0发送一个字符函数 *************************************************************/ void USART0_SendByte(uint8_t c) { /*等待发送缓冲器为空*/ while((USART0->US_CSR & US_CSR_TXEMPTY) == 0); USART0->US_THR=c; //将发送字符写入发送保持寄存器 } /*************************************************************** * 函数名:USART0_SendString() * 参数 :uint8_t *s 指向字符串的指针 * 返回值:void * 描述 :USART0发送字符串函数 *************************************************************/ void USART0_SendString(uint8_t *s) { while(*s) //判断是否到字符串末尾 { USART0_SendByte(*s); //发送指针当前所指的字节 s++; //地址加1 } } 在main.c中写个简单的测试程序,如下: int main(void) { systick_hw_init(); led_hw_init(); USART0_Init(115200); USART0_SendString("hello,this is a usart demo!\r\n"); while(1){ USART0_SendString("hello,I am SAM4N!\r\n"); led_hw_on(); delay_ms(500); led_hw_off(); delay_ms(500); } } 找一条串口线接到PA5和PA6上就可以看到输出了,效果和上一节一样。注意串口线要用TTL电平的哦。 |