Keil uVision5开发一个基于LPC17XX系列芯片的工程文件 |
您所在的位置:网站首页 › lcp下载 › Keil uVision5开发一个基于LPC17XX系列芯片的工程文件 |
1 如何使用keil5建立一个工程文件 本篇文章所讲内容基于LPC1759芯片展开(公司用LPC比较多,M0、M3都用,对于LPC系列芯片,开发流程大同小异,如果以后用到STM32再总结跟大伙分享),比较完整地展现一个软件项目的开发,内容比较基础,希望对一些刚入门的同学有些帮助。(PS:我也是菜鸟,从事应用层的开发已经两年多,但是最近才着手负责一个较完整的小项目,期间的一些小感悟、小收获非常乐意拿出来跟大家交流分享,不对的地方还请各位高手赐教哈~ 打开keil5软件(需要软件安装包的同学私我哈,keil5安装包,以及AK100仿真器驱动都可以提供),创建一个新工程文件,如图1所示。 图1 取文件名称:lpc1759example,如图2所示。 图2 进入选择MCU界面,如图3所示。 图3 通过Manage Run-Time Environment可把keil5工具提供的针对开发者所选的MCU的软件功能加载到文件中,我一般就按照图4所示选择。 图4 说几点,本文创建的工程文件为前后台模式,不采用任何实时操作系统,如果你对keil5工具自带的RTX感兴趣,可以进一步研究,目前我们公司开发用的都是UCOS。另外不太建议直接从Manage Run-Time Environment中加载比如GPIO、UART等等硬件相关的代码,一般针对某款MCU开发时,大多数情况下都可以从网上获得相关的开发例程,如各个硬件初始化、简单应用代码等。所以,建议采用开发例程的代码。 如图5所示,一个初步的工程文件搭建好了,接下来的工作主要就是配置工程文件、加载自己编写的代码丰富工程文件功能。 图5 如图6所示,在"Target1"位置右击,点击“Manage Project Items”,进入图7所示界面,可以增加、删除“Project Targets”"Groups",或者修改名称。还有重要一步,就是配置目标选项。
图6
图7
图8、图9跟所选芯片相关,图8就是选择的MCU,图9的ROM、RAM大小自动跟图8所选芯片匹配,采用默认即可。 图8
图9
图10注意勾选“Create Hex File”,否则编译完程序在output里找不到hex文件,图11、图12、图13、图14、图15采用默认配置即可。 图10
图11
图12
图13
图15 图16需要注意的是,你所用的仿真器选择,在这之前一定要安装好仿真器的驱动,否则在图16里找不到你要配置的仿真器,目前我都是用AK100仿真器,对应的就是“TKScope Debug for ARM”,然后点击右边的“Settings”按钮。如图17所示,进行“硬件选择”配置,如图18所示,进行“程序烧写”配置,其他选项可以不用改动,感兴趣的话再细究。 图16
图17 图18
2 开始编写代码 在编写代码前,要根据项目的功能要求,确定使用哪些硬件,根据硬件使用情况,决定主频、外设频率大小。 (这个时候,手头上肯定要准备好芯片用户手册和相关开发例程)。关于主频该取多大,一是考虑芯片最大支持多少,肯定不能超过芯片的要求,二是如果外设使用的不太多也不复杂,建议主频不要太大,太大功耗大,太小对于SPI等读写速率有影响,对于lpc1759,主频定为48MHz(外部晶振频率为12MHz)或主频定为44236800Hz(外部晶振频率为11059200Hz),统一外设频率定为二分之一的主频,至于SPI的CLK到底多大,可以通过SPI相关寄存器分频设置。主频、外设频率设定等系统初始化(一般main函数的首行代码),在“system_LPC17xx.c”文件里修改,内容比较少也比较简单,遇到一些寄存器的设置,可以查用户手册。 如图19所示,新建一个文件,按照图20所示保存。 图19 图20
把main.c文件加载到工程里的UserCode下,如图21所示。接下来开始编写main函数框架,一个简单的框架如图22所示。之后的工作就是根据项目要求,一点一点添加功能,应用层或底层驱动都会涉及到。 图21 图22 3 使用一个硬件,要编写哪些代码? 这一小节,通过UART的例子,跟大家详解一下。牵扯到硬件,对于菜鸟而言,有例程会大大降低开发难度,也容易避免掉进不知名的坑里。用到硬件,首先要初始化,参考例程加上查询芯片用户手册,根据自己的应用要求,写好应该不难。 void UART_Ini(uint8_t PortNum, UARTMODE set,uint32_t baudrate) { uint16_t ulFdiv; //参数过滤保护 if((set.datab8)) return; if( (set.stopb==0)||(set.stopb>2) ) return; if( set.parity>4 ) return; if(PortNum == 0) //UART0 { LPC_PINCON->PINSEL0 |= (0x01 LCR = 0x80; //允许设置波特率 ulFdiv = (Fpclk /16) / baudrate; //设置波特率 Fpclk为外设频率 LPC_UART0->DLM = ulFdiv / 256; LPC_UART0->DLL = ulFdiv % 256; LPC_UART0->LCR = 0x00; //锁定波特率 LPC_UART0->FCR = 0x87; //使能FIFO 设置8个字节触发点 LPC_UART0->LCR |= (set.datab-5); //数据位设置 if(set.stopb ==2 ) //2位停止位 { LPC_UART0->LCR |= 0x04; } if(set.parity !=0 ) //有校验位 { LPC_UART0->LCR |= 0x08; LPC_UART0->LCR |=((set.parity-1) if (GETBIT(ui_FlgUART[UART0],6)) //在发送状态中 { for (i=0; i CLRBIT(ui_FlgUART[UART0],6); uc_UartPtrTx[UART0] = 0; uc_UartPtrRx[UART0] = 0; LPC_UART0->IER = 0x01; //使能接收中断 goto End; } LPC_UART0->THR = uc_UartTxbuf[UART0][uc_UartPtrTx[UART0]]; uc_UartPtrTx[UART0] ++ ; } goto Start; } else { LPC_UART0->IER = 0x01; //使能接收中断 } } if((LPC_UART0->IIR & 0x0F ) == 0x04 ||(LPC_UART0->IIR & 0x0F ) == 0x0C) //接收数据 { if(!GETBIT(ui_FlgUART[UART0],6)) //不在发送状态 { s_Tmr10ms.ui_UartRxTimeOut[UART0] = 5; for(i=0; i uint8_t uc_Buf; uc_Buf = LPC_UART0->RBR; break; } uc_UartRxbuf[UART0][uc_UartPtrRx[UART0]] = LPC_UART0->RBR; //接收数据 uc_UartPtrRx[UART0] ++ ; uc_UartRxLen[UART0] = uc_UartPtrRx[UART0]; } goto Start; } else { LPC_UART0->IER = 0x02; //使能发送中断 } } End:; }
在接收数据中断里,通过 s_Tmr10ms.ui_UartRxTimeOut字节超时定时器,来判断数据收没收全,时间到了,数据接收标志置起(在10ms定时器里做)。对于一些有固定帧头帧尾格式的数据报文,在接收里可做详细判断,不必采用字节超时方法。在main函数的主循环中,接收数据处理代码如图24所示。ui_FlgUART[UARTNum]的bit1位即为接收数据标志。
接收完数据做了相关处理后,要发送回复数据,代码构成如图25所示。
void SetRTS(eUARTNum UARTNum) { ui_FlgUART[UARTNum] |= 0x0020; //setbit 5 uc_UartPtrTx[UARTNum] = 0; } 如果是通过硬件RTS控制数据发送的话,SetRTS里还要增加相关的硬件控制,我这里就是置起发送标志,另外清除了一下发送数据长度。
void StartTD485(eUARTNum UARTNum) //发送启动函数 { uc_UartPtrTx[UARTNum] = 0; memset(uc_UartRxbuf[UARTNum],0,sizeof(uc_UartRxbuf[UARTNum])); SETBIT(ui_FlgUART[UARTNum],6); CLRBIT(ui_FlgUART[UARTNum],5); if(UARTNum==UART0) { LPC_UART0->THR = uc_UartTxbuf[UART0][uc_UartPtrTx[UART0]]; uc_UartPtrTx[UART0] ++ ; if(uc_UartPtrTx[UART0] >= uc_UartTxLen[UART0]) //发送完数据 { CLRBIT(ui_FlgUART[UART0],6); uc_UartPtrTx[UART0] = 0; uc_UartPtrRx[UART0] = 0; LPC_UART0->IER = 0x01; //使能接收中断 return; } if( uc_UartPtrTx[UART0]!=0) { LPC_UART0->IER = 0x02; //使能发送中断还有未发送完的数据进入发送中断接着发送 } } } 使用UART收发数据,基本就涉及到以上方面。
最后附一张,我做的一个小项目的工程文件结构图26。建议大家,应用层代码、不同硬件的底层代码放在不同的文件目录里,方面维护,增加或删除文件都比较方便,养成好习惯哦~
代码功能完成好了,接下来就是结合硬件仿真调试了,期间可能会出现各种各样的问题,多跟硬件工程师沟通,很重要哦~
|
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |