本以为写过了查询方式,又有ZLG的代码,测试下应该没有什么问题,不过真的是问题多多啊,很多没有弄明白的地方。
还是用KEIL FOR ARM,器件,环境选择如下
然后用KEIL给的模板,把ZLG 《深入浅出ARM7-LPC213X...》的程序敲进去,略微改动,
#include <LPC21xx.H> /* LPC21xx definitions */
#include "Main.h" //包含数据类型定义
/*定义串口模式设置数据结构*/
typedef struct UartMode
{
UINT8 datab; //字长度,5/6/7/8可选
UINT8 stopb; //停止位,1/2可选
UINT8 parity; //奇偶校验位,0;无校验;1:奇校验;2:偶校验
}UARTMODE;
UINT8 rcv_buf[8]; // UART0 数据接收缓冲区
volatile UINT8 rcv_new; // 接受新数据标志
/*********************************************************************************************************
** 函数名称: IRQ_UART0()
** 函数功能: 串口0接受中断服务程序
** 入口参数: 无
** 出口参数: 无
********************************************************************************************************/
void __irq IRQ_UART0(void)
{
UINT8 i;
if((U0IIR & 0x0f) == 0x04)
rcv_new = 1; //设置接收到新的数据标志
for(i=0; i<8; i++) //FIFO使能时设为8字节长度
{
rcv_buf = U0RBR; //读取FIFO的数据,并清除中断
}
VICVectAddr = 0x00; // 中断处理结束
}
/*********************************************************************************************************
** 函数名称: UART0_SendByte()
** 函数功能: 向串口0发送1字节数据
** 入口参数: dat 要发送的数据
** 出口参数: 无
********************************************************************************************************/
void UART0_SendByte(UINT8 dat)
{
U0THR = dat; //要发送的数据
}
/*********************************************************************************************************
** 函数名称: UART0_SendBuf()
** 函数功能: 向串口0发送8字节数据
** 入口参数: 无
** 出口参数: 无
**********************************************************************************************************/
void UART0_SendBuf(void)
{
UINT8 i;
for(i=0; i<8; i++)
UART0_SendByte(rcv_buf);
while((U0LSR & 0x20) == 0); //等待数据发送完毕
}
/*********************************************************************************************************
** 函数名称: UART0_Init()
** 函数功能: 串口初始化,设置工作模式和波特率
** 入口参数: baud 波特率
set 模式设置(UARTMODE 数据结构)
** 出口参数: 1为初始化成功,0为初始化失败
**********************************************************************************************************/
UINT8 UART0_Init(UINT32 baud, UARTMODE set)
{
UINT32 bak;
/* 参数过滤 */
if((baud == 0) || (baud > 115200))
return 0;
if((set.datab < 5) || (set.datab > 8))
return 0;
if((set.stopb == 0) || (set.stopb > 2))
return 0;
if((set.parity > 4))
return 0;
// 设置串口波特率
U0LCR = 0x80; // DLAB = 1
bak = (Fpclk >> 4) / baud;
U0DLM = bak >> 8;
U0DLL = bak & 0xFF; // DLAB = 0
// 设置串口模式 //已在U0LCR中设置
bak = set.datab - 5; // 设置字长
if (set.stopb == 2) bak |= 0x04; // 判断是否为2位停止位
if (set.parity != 0)
{
set.parity = set.parity - 1;
bak |= 0x08;
}
bak |= set.parity << 4; // 设置奇偶校验
U0LCR = bak;
return(1);
}
/*********************************************************************************************************
** 函数名称: main()
** 函数功能: 从串口 UART0 接受字符串,并发送回上位机显示
** 调试说明: 需要 PC 串口显示终端软件
**********************************************************************************************************/
int main (void)
{
UARTMODE set;
set.datab = 8;
set.stopb = 1;
set.parity = 0;
rcv_new = 0;
PINSEL0 = (PINSEL0 & (~0x0f)) | 0x05; //设置IO为UART0
UART0_Init(UART_BPS,set); //串口初始化
U0FCR = 0x81; //使能 FIFO,并设置出发点为8字节
U0IER = 0x01; //允许 RBR 中断,即接受中断
IRQEnable(); //使能IRQ 中断,此函数在ZLG的lpc2131模版中
/*使能 UART0 中断*/
VICIntSelect = 0x00000000; //设置所有的通道为 IRQ 中断
VICVectCntl0 = 0x20 | 0x06; // UART0 分配到IRQ slot0,即最高优先级
VICVectAddr0 = (UINT32)IRQ_UART0; //设置UART0 向量地址
VICIntEnable = 1 << 0x06; //使能UART0 中断
while(1)
{
if (rcv_new == 1) //如果有新数据
{
rcv_new = 0; //清除标志,以接受新数据
UART0_SendBuf();
}
}
// return 0;
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
编译时首先发现 //使能IRQ 中断 这里有错误,原来这是ZLG在ADS的LPC2131模板中的一个宏定义,但是KEIL下没有,要自己写。翻书在中断那一章中发现有这么一句话“设置 CPSR 寄存器的I位或者F位,需要在特权模式下,可在启动代码中设置
在startup.s中将
MSR CPSR_c, # 0xdf;
LDR SP, =StackUsr
中的 0xdf 改为 0x5f
”
发现这也是根据ADS中的LPC2100模板说的,KEIL的模板不一样,试图去改也没有成功,把IRQEnable(); 注释掉可以编译成功,但是结果是只能收发一个字节的数据,应该是没有开IRQ的中断。
(其实是波特率不对!,不要做下面的更改,误导了,当时以为是正确的)
所以找了ZLG的LPC2131模板,把其中startup.s中的
SoftwareInterrupt
; B SoftwareInterrupt
;//增加开/关中断处理 Chenxibing-2004-02-09
CMP R0, #4
LDRLO PC, [PC, R0, LSL #2]
MOVS PC, LR
SwiFunction
DCD IRQDisable ;0
DCD IRQEnable ;1
DCD FIQDisable ;2
DCD FIQEnable ;3
IRQDisable
;关IRQ中断
MRS R0, SPSR
ORR R0, R0, #NoInt
MSR SPSR_c, R0
MOVS PC, LR
IRQEnable
;开IRQ中断
MRS R0, SPSR
BIC R0, R0, #NoInt
MSR SPSR_c, R0
MOVS PC, LR
FIQDisable
;关FIQ中断
MRS R0, SPSR
ORR R0, R0, #NoFIQ
MSR SPSR_c, R0
MOVS PC, LR
FIQEnable
;开FIQ中断
MRS R0, SPSR
BIC R0, R0, #NoFIQ
MSR SPSR_c, R0
MOVS PC, LR
;// Changed 2004-12-09
加入到KEIL的startup.s的
; Initialise Interrupt System
; ...
处,
然后再把ADS模板中target.h中的
__swi(0x00) void SwiHandle1(int Handle);
#define IRQDisable() SwiHandle1(0)
#define IRQEnable() SwiHandle1(1)
#define FIQDisable() SwiHandle1(2)
#define FIQEnable() SwiHandle1(3)
加入到KEIL工程中的头文件中,
再编译可以,下载到板子上,reset,发 12345678 8个字符的字符串,发了三次用串口助手可以自收发了,如图,红线划得部分.
但是却有一个大大的问题想不通!!!大约过了15秒,没有任何操作,会自动的收到一些码。这之后再发数据就收不到任何数据了。期待解答啊。。。
15秒对ARM来说应该是个很漫长的过程啊,为什么这么久才出错?
(这个问题依然未知,但是此程序的PLL频率和波特率都不停变化,可能是原因)
文章评论(0条评论)
登录后参与讨论