LPC824串口+定时器(MRT)配置完成串口的收发数据

1.使用开关矩阵将对应的IO口复用到串口上

我这里使用的是串口0,p0_4复用为Usart0的TX引脚,p0_0复用到Usart0的RX引脚,这颗NXP芯片内置了开关矩阵,所以在使用反面就相对比较方便了,可以将任意一个IO口复用成你需要的模式,但是使用的时候要注意的是一些特定的引脚,像下载调试用的SWDIO和SWCLK这两个引脚就已经被占用的

 

LPC824Lite这个开发板使用方便的地方就是板载了一个LPC11U35的芯片,因此在调试下载的时候就比较方便了,不需要另外接下载线,直接用DAP,即可以当电源线,下载调试线也可以当串口线 ,所以我这里也是直接用0和4两个引脚当串口使用(使用DAP下载程序的时候需要在Debug里面选中CMSIS-DAP Debugger)

 

 最后查看SWM关于串口0的寄存器,是在SWM的寄存器0上,因此吧U0_TX_O赋值为4(即使用P0_4当串口0的TX),RX类似

最后附上代码

LPC_SYSCTL->SYSAHBCLKCTRL|=1<<7;  //开启SWM时钟
LPC_SWM->PINASSIGN[0]&=~0xFFFF;
LPC_SWM->PINASSIGN[0]|=0x04;
LPC_SYSCTL->SYSAHBCLKCTRL&=~(1<<7);  //关闭SWM时钟(使用完之后记得关闭,节省功耗)

2.配置串口寄存器

串口的时钟源都是来自一个U_PCLK的时钟,这个时钟是由主时钟经过两次分频得到的(这里的主时钟不是系统时钟,主时钟是60M,系统时钟是经过主时钟2分频得到的为30M) ,U_PCLK的时钟在SYSCON里面可以进行配置

U_PCLK=(((60000000/LPC_SYSCTL->UARTCLKDIV)*256)/(uint64_t) (256 + LPC_SYSCON->UARTFRGMULT))

UARTCLKDIV控制U_PCLK的整数分频UARTFRGMULT控制U_PCLK的小数分频

在LPC_USART0->CFG寄存器里配置串口的数据位停止位相关配置

LPC_SYSCTL->SYSAHBCLKCTRL|=1<<14;  //开启USART0时钟
LPC_SYSCTL->PRESETCTRL&=~(0x1<<3);  //开启复位USART0
LPC_SYSCTL->PRESETCTRL|=(0x1<<3);  //关闭复位USART0
LPC_USART0->CFG|=1<<0;             //配置串口寄存器
LPC_USART0->CFG|=1<<2;
	
LPC_SYSCTL->UARTCLKDIV=60000000/(9600*100);    //配置串口的时钟输入U_PCLK
LPC_SYSCON->UARTFRGDIV=0xFF;
LPC_SYSCON->UARTFRGMULT=((60000000/LPC_SYSCTL->UARTCLKDIV)*256)/60000000/(9600*100);
	
DEBUG_UART->BRG=(((60000000/LPC_SYSCTL->UARTCLKDIV)*256)/(uint64_t) (256 +LPC_SYSCON->UARTFRGMULT))/(16*9600)-1;

3.经过前面两步已经实现了串口的发送数据,现在要开启串口的接受中断

LPC_USART0->INTENSET|=1<<0;     //开启串口接受中断
NVIC->ISER[0]|=1<<3;

4.编写串口中断处理函数

/*
    UsartRxBuff:接受串口数据的BUFF
    UsartRxDataLen:标志接受数据的长度
    用定时器来判断一帧数据时候接受完毕若定时器定时时间 到串口还没有接受到数据则表示串口接受完了一帧数据,因此每次进入串口中断的时候都要将定时器复位
*/
void UART0_IRQHandler(void)
{
	UsartRxBuff[UsartRxDataLen]=LPC_USART0->RXDATA;
	UsartRxDataLen++;
	LPC_MRT_CH0->INTVAL=30000000/1;    //设置分频(这两行是定时器的,后面会有讲到)
	LPC_MRT_CH0->CTRL|=1<<0;	    //开启定时器
}

5.初始化定时器MRT

/*
我这里是将定时器初始化为1S产生一次中断,MRT里有四个定时器,可以单独配置成不同的分频系数和重装值
在CTRL寄存器里可以配置定时器的模式,我这里配置的时循环进入中断模式Repeat interrupt mode.使能定时器也是在CTRL里面配置
*/
/*
函数功能:定时器初始化
*/
void TimerInit(void)
{
	LPC_SYSCON->SYSAHBCLKCTRL|=1<<10;  //开启定时器时钟
	LPC_SYSCON->PRESETCTRL&=~(1<<7);   //复位MRT
	LPC_SYSCON->PRESETCTRL|=1<<7;
	NVIC->ISER[0]|=1<<10;              //开启定时器中断
	LPC_MRT_CH0->INTVAL=30000000/1;    //设置分频
	LPC_MRT_CH0->INTVAL|=0x80000000;   
	LPC_MRT_CH0->STAT|=1<<0;           //清除中断标志位
	LPC_MRT_CH0->CTRL|=1<<0;					 //开启定时器
}

6.编写定时器中断处理函数

/*
函数功能:定时器中断处理函数
*/
void MRT_IRQHandler(void)
{
	uint32_t int_pend;
	/* Get interrupt pending status for all timers */
	int_pend = Chip_MRT_GetIntPending();
	Chip_MRT_ClearIntPending(int_pend);
	LPC_MRT_CH0->CTRL&=~(1<<0);		//接受完一帧数据,关闭定时器
	UsartRxFlag=1;     //标志位值1,告诉main函数接受到数据
}	

7.main函数里面做数据处理

if(UsartRxFlag==1)
{
	UsartRxFlag=0;
	UsartRxBuff[UsartRxDataLen]='\0';
	UsartSendStr(LPC_USART0,UsartRxBuff);
	UsartRxDataLen=0;
}

8.串口发送函数

我这里写的串口发送函数不够完善,是根据结束符判断字符串时候结束,所以传进来的字符串必须要有结束符,改善的话还可以加一个长度限制,或者其他

/*
函数功能:串口发送字符串
*/
void UsartSendStr(LPC_USART_T *pUART,uint8_t *str)
{
	while(*str!='\0')
	{
		while((LPC_USART0->STAT&(1<<2))!=0)
		{
			LPC_USART0->TXDATA=*str;
			str++;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42174355/article/details/85836177
今日推荐