天嵌 ARM开发社区

 找回密码
 注册
查看: 2352|回复: 2

TQ210裸机编程(7)——UART+key(中断)

[复制链接]
freewing 发表于 2014-6-8 01:03:22 | 显示全部楼层 |阅读模式
之前的按键中断程序是直接下载到DDR内存运行的,这次结合时钟和串口的知识,改善按键中断实验的程序。

运行效果:

Key and Uart Test
You are pressed key:1
You are pressed key:1
You are pressed key:1
You are pressed key:3
You are pressed key:2
You are pressed key:3
You are pressed key:4
You are pressed key:4




直接上代码

start.S





[cpp] view plaincopy
01..global _start                  /* 声明一个全局的标号 */  
02..global key_isr  
03._start:  
04.  
05.    bl clock_init  
06.    bl uart_init  
07.  
08.    /* 开总中断 */  
09.    mrs r0, cpsr  
10.    bic r0, r0, #0x00000080     /* 清楚第7位,IRQ中断禁止位,写0使能IRQ */  
11.    msr cpsr, r0  
12.  
13.    bl main                     /* 跳转到C函数去执行 */  
14.  
15.halt:  
16.    b halt  
17.  
18.key_isr:  
19.    /* 计算返回地址:PC的值等于当前执行的地址+8,
20.    ** 当CPU正要执行某条指令时(还未执行),被中断,
21.    ** 这时这条刚要执行的指令的地址刚好=PC-4 */  
22.    sub lr, lr, #4  
23.    stmfd sp!, {r0-r12, lr}     /* 保护现场 */  
24.    bl key_handle  
25.    /* 恢复现场 */  
26.    ldmfd sp!, {r0-r12, pc}^    /* ^表示把spsr恢复到cpsr */  
注意:在start.S中没有设置栈,是因为S5PV210在出厂时,samsung为其固化在iROM中的代码已经为我们设置好了栈。

clock.c





[cpp] view plaincopy
01.#define APLLCON0        *((volatile unsigned int *)0xE0100100)  
02.#define MPLLCON         *((volatile unsigned int *)0xE0100108)  
03.#define EPLLCON0        *((volatile unsigned int *)0xE0100110)  
04.#define VPLLCON         *((volatile unsigned int *)0xE0100120)  
05.#define CLK_SRC0        *((volatile unsigned int *)0xE0100200)  
06.#define CLK_DIV0        *((volatile unsigned int *)0xE0100300)  
07.#define CLK_DIV1        *((volatile unsigned int *)0xE0100304)  
08.#define CLK_DIV2        *((volatile unsigned int *)0xE0100308)  
09.#define CLK_DIV3        *((volatile unsigned int *)0xE010030C)  
10.  
11.void clock_init()  
12.{  
13.    /* 1、设置PLL_LOCK寄存器(这里使用默认值) */  
14.    /* 2、设置PLL_CON寄存器(使用芯片手册推荐的值) */  
15.    APLLCON0    = (1 << 0) | (3 << 8) | (125 << 16) | (1 << 31);    /* FOUTAPLL = 1000MHz */  
16.    MPLLCON     = (1 << 0) | (12 << 8) | (667 << 16) | (1 << 31);   /* FOUTMPLL = 667MHz */  
17.    EPLLCON0    = (1 << 0) | (12 << 8) | (667 << 16) | (1 << 31);   /* FOUTEPLL = 96MHz */  
18.    VPLLCON     = (3 << 0) | (6 << 8) | (108 << 16) | (1 << 31);    /* FOUTVPLL = 54MHz */  
19.      
20.    /* 3、选择PLL为时钟输出 */  
21.    /* MOUT_MSYS = SCLKAPLL = 1000MHz
22.    ** MOUT_DSYS = SCLKMPLL = 667MHz
23.    ** MOUT_PSYS = SCLKMPLL = 667MHz
24.    */  
25.    CLK_SRC0 = (1 << 0) | (1 << 4) | (1 << 8) | (1 << 12);  
26.      
27.    /* 4、设置系统时钟分频值 */  
28.    /* freq(ARMCLK) = MOUT_MSYS / (APLL_RATIO + 1) = 1000MHz / (0 + 1) = 1000MHz
29.    ** freq(HCLK_MSYS) = ARMCLK / (HCLK_MSYS_RATIO + 1) = 1000MHz / (4 + 1) = 200MHz
30.    ** freq(PCLK_MSYS) = HCLK_MSYS / (PCLK_MSYS_RATIO + 1) = 200MHz / (1 + 1) = 100MHz
31.    ** freq(HCLK_DSYS) = MOUT_DSYS / (HCLK_DSYS_RATIO + 1) = 667 / (3 + 1) = 166MHz
32.    ** freq(PCLK_DSYS) = HCLK_DSYS / (PCLK_DSYS_RATIO + 1) = 166 / (1 + 1) = 83MHz
33.    ** freq(HCLK_PSYS) = MOUT_PSYS / (HCLK_PSYS_RATIO + 1) = 667 / (4 + 1) = 133MHz
34.    ** freq(PCLK_PSYS) = HCLK_PSYS / (PCLK_PSYS_RATIO + 1) = 133 / (1 + 1) = 66MHz
35.    */  
36.    CLK_DIV0 = (0 << 0) | (4 << 8) | (1 << 12) | (3 << 16) | (1 << 20) | (4 << 24) | (1 << 28);  
37.}  



uart.c





[cpp] view plaincopy
01.#define GPA0CON     *((volatile unsigned int *)0xE0200000)  
02.#define ULCON0      *((volatile unsigned int *)0xE2900000)  
03.#define UCON0       *((volatile unsigned int *)0xE2900004)  
04.#define UFCON0      *((volatile unsigned int *)0xE2900008)  
05.#define UTRSTAT0    *((volatile unsigned int *)0xE2900010)  
06.#define UTXH0       *((volatile unsigned int *)0xE2900020)  
07.#define URXH0       *((volatile unsigned int *)0xE2900024)  
08.#define UBRDIV0     *((volatile unsigned int *)0xE2900028)  
09.#define UDIVSLOT0   *((volatile unsigned int *)0xE290002C)  
10.  
11./*
12.** UART0初始化
13.*/  
14.void uart_init()  
15.{  
16.    /*
17.    ** 配置GPA0_0为UART_0_RXD
18.    ** 配置GPA0_1为UART_0_TXD
19.    */  
20.    GPA0CON &= ~0xFF;  
21.    GPA0CON |= 0x22;  
22.  
23.    /* 8-bits/One stop bit/No parity/Normal mode operation */  
24.    ULCON0 = 0x3 | (0 << 2) | (0 << 3) | (0 << 6);  
25.  
26.    /* Interrupt request or polling mode/Normal transmit/Normal operation/PCLK/*/  
27.    UCON0 = 1 | (1 << 2) | (0 << 10);  
28.  
29.    /* 静止FIFO */  
30.    UFCON0 = 0;  
31.  
32.    /*
33.    ** 波特率计算:115200bps
34.    ** PCLK = 66MHz
35.    ** DIV_VAL = (66000000/(115200 x 16))-1 = 35.8 - 1 = 34.8
36.    ** UBRDIV0 = 34(DIV_VAL的整数部分)
37.    ** (num of 1's in UDIVSLOTn)/16 = 0.8
38.    ** (num of 1's in UDIVSLOTn) = 12
39.    ** UDIVSLOT0 = 0xDDDD (查表)
40.    */  
41.    UBRDIV0 = 34;  
42.    UDIVSLOT0 = 0xDDDD;  
43.}  
44.  
45.void uart_send_byte(unsigned char byte)  
46.{  
47.    while (!(UTRSTAT0 & (1 << 2)));   /* 等待发送缓冲区为空 */  
48.    UTXH0 = byte;                   /* 发送一字节数据 */         
49.}  
50.  
51.unsigned char uart_recv_byte()  
52.{  
53.    while (!(UTRSTAT0 & 1));    /* 等待接收缓冲区有数据可读 */  
54.    return URXH0;               /* 接收一字节数据 */         
55.}  
56.  
57.void uart_send_string(char *str)  
58.{  
59.    char *p = str;  
60.    while (*p)  
61.        uart_send_byte(*p++);  
62.}  



key.c





[cpp] view plaincopy
01.#define GPH0CON             *((volatile unsigned int *)0xE0200C00)  
02.#define GPH0DAT             *((volatile unsigned int *)0xE0200C04)  
03.  
04.#define EXT_INT_0_CON       *((volatile unsigned int *)0xE0200E00)  
05.#define EXT_INT_0_MASK      *((volatile unsigned int *)0xE0200F00)  
06.  
07.#define VIC0INTSELECT       *((volatile unsigned int *)0xF200000C)  
08.#define VIC0INTENABLE       *((volatile unsigned int *)0xF2000010)  
09.  
10.#define VIC0VECTADDR0       *((volatile unsigned int *)0xF2000100)  
11.#define VIC0VECTADDR1       *((volatile unsigned int *)0xF2000104)  
12.#define VIC0VECTADDR2       *((volatile unsigned int *)0xF2000108)  
13.#define VIC0VECTADDR3       *((volatile unsigned int *)0xF200010C)  
14.  
15.#define VIC0ADDRESS         *((volatile unsigned int *)0xF2000F00)  
16.  
17.#define EXT_INT_0_PEND      *((volatile unsigned int *)0xE0200F40)  
18.  
19.extern void key_isr(void);  
20.  
21.void key_handle()  
22.{     
23.    volatile unsigned char key_code = EXT_INT_0_PEND & 0xF;  
24.    volatile unsigned char key = 0;  
25.      
26.    VIC0ADDRESS = 0;        /* 清中断向量寄存器 */  
27.    EXT_INT_0_PEND |= 0xF;  /* 清中断挂起寄存器 */  
28.      
29.    if (key_code == 1)      /* key1 */  
30.        key = '1';  
31.    else if (key_code == 2) /* key2 */  
32.        key = '2';  
33.    else if (key_code == 4) /* key3 */  
34.        key = '3';  
35.    else if (key_code == 8) /* key4 */  
36.        key = '4';  
37.  
38.    uart_send_string("You are pressed key:");  
39.    uart_send_byte(key);  
40.    uart_send_string("\r\n");  
41.  
42.}  
43.  
44.int main()  
45.{  
46.    GPH0CON |= 0xFFFFFFFF << 0;                               /* 配置GPH0[0.1.2.3]为外部中断:key1.key2.key3.key4 */  
47.      
48.    EXT_INT_0_CON &= ~(0xFF << 0);  
49.    EXT_INT_0_CON |= 2 | (2 << 4) | (2 << 8) | (2 << 12); /* 配置EXT_INT[0.1.2.3]为下降沿触发 */  
50.    EXT_INT_0_MASK &= ~0xF;                 /* 取消屏蔽外部中断EXT_INT[0.1.2.3] */  
51.      
52.    VIC0INTSELECT &= ~0xF;                  /* 选择外部中断EXT_INT[0.1.2.3]为IRQ类型的中断 */  
53.      
54.    VIC0INTENABLE |= 0xF;                       /* 使能外部中断EXT_INT[0.1.2.3] */  
55.      
56.    /* 当EXT_INT[0]触发中断,即用户按下key1时,
57.    ** CPU就会自动的将VIC0VECTADDR0的值赋给VIC0ADDRESS并跳转到这个地址去执 */  
58.    VIC0VECTADDR0 = (unsigned int)key_isr;  /* key1 */  
59.    VIC0VECTADDR1 = (unsigned int)key_isr;  /* key2 */  
60.    VIC0VECTADDR2 = (unsigned int)key_isr;  /* key3 */  
61.    VIC0VECTADDR3 = (unsigned int)key_isr;  /* key4 */  
62.      
63.    uart_send_string("\r\nKey and Uart Test\r\n");  
64.    while (1);  
65.      
66.    return 0;  
67.}  


Makefile



[cpp] view plaincopy
01.key.bin: start.o clock.o uart.o key.o  
02.    arm-linux-ld -Ttext 0xD0020010 -o key.elf $^  
03.    arm-linux-objcopy -O binary key.elf $@  
04.    arm-linux-objdump -D key.elf > key.dis  
05.      
06.%.o : %.c  
07.    arm-linux-gcc -c $< -o $@  
08.%.o : %.S  
09.    arm-linux-gcc -c $< -o $@  
10.      
11.clean:  
12.    rm *.o *.elf *.bin *.dis  


程序烧写过程见《TQ210裸机编程(5)——系统时钟配置》




转载请注明来源:http://blog.csdn.net/zjhsucceed_329/
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-5-3 03:12 , Processed in 1.031250 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表