ARM波形控制-作业

实现K2 按下蜂鸣器发声 按下k3 蜂鸣器停止发声(请上传演示视频及源码)

1. main.c 代码:

//uart
#define GPA1CON 	0x11400020
#define ULCON2 		0x13820000
#define UCON2 		0x13820004
#define UBRDIV2 	0x13820028
#define UFRACVAL2  	0x1382002c
#define UTXH2 		0x13820020
#define UTRSTAT2 	0x13820010

#define rGPA1CON 	(*(volatile unsigned int*)GPA1CON)
#define rULCON2 	(*(volatile unsigned int*)ULCON2)
#define rUCON2 		(*(volatile unsigned int*)UCON2)
#define rUBRDIV2 	(*(volatile unsigned int*)UBRDIV2)
#define rUFBRACVAL2 (*(volatile unsigned int*)UFRACVAL2)
#define rUTXH2 		(*(volatile unsigned int*)UTXH2)
#define rUTRSTAT2 	(*(volatile unsigned int*)UTRSTAT2)


//interrupt
#define GPX1CON 		0x11000c20
#define EXT_INT41CON 	0x11000E04
#define EXT_INT41_MASK 	0x11000F04
#define ICDISER1_CPU0 	0x10490104
#define ICDDCR 			0x10490000
#define ICCPMR_CPU0 	0x10480004
#define ICCICR_CPU0 	0x10480000
#define ICCIAR_CPU0 	0x1048000C
#define EXT_INT41_PEND 	0X11000F44
#define ICDICPR1_CPU0 	0x10490284
#define ICCEOIR_CPU0 	0x10480010
#define ICDIPTR14_CPU0 	0x10490838

#define rGPX1CON 		(*(volatile unsigned int*)GPX1CON)
#define rEXT_INT41CON 	(*(volatile unsigned int*)EXT_INT41CON)
#define rEXT_INT41_MASK (*(volatile unsigned int*)EXT_INT41_MASK)
#define rICDISER1_CPU0 	(*(volatile unsigned int*)ICDISER1_CPU0)
#define rICDDCR 		(*(volatile unsigned int*)ICDDCR)
#define rICCPMR_CPU0 	(*(volatile unsigned int*)ICCPMR_CPU0)
#define rICCICR_CPU0 	(*(volatile unsigned int*)ICCICR_CPU0)
#define rICCIAR_CPU0 	(*(volatile unsigned int*)ICCIAR_CPU0)
#define rEXT_INT41_PEND (*(volatile unsigned int*)EXT_INT41_PEND)
#define rICDICPR1_CPU0 	(*(volatile unsigned int*)ICDICPR1_CPU0)
#define rICCEOIR_CPU0 	(*(volatile unsigned int*)ICCEOIR_CPU0)
#define rICDIPTR14_CPU0 (*(volatile unsigned int*)ICDIPTR14_CPU0)


//PWM
#define GPD0CON 		0x114000A0
#define TCFG0 			0x139D0000
#define TCFG1 			0x139D0004
#define TCNTB0 			0x139D000C
#define TCMPB0      	0x139D0010
#define TCON        	0x139D0008

#define rGPD0CON 		(*(volatile unsigned int*)GPD0CON)
#define rTCFG0 			(*(volatile unsigned int*)TCFG0)
#define rTCFG1 			(*(volatile unsigned int*)TCFG1)
#define rTCNTB0 		(*(volatile unsigned int*)TCNTB0)
#define rTCMPB0     	(*(volatile unsigned int*)TCMPB0)
#define rTCON       	(*(volatile unsigned int*)TCON)


void uart_putc(char c);
void do_irq(void);
void do_pwm_start(void);
void do_pwm_over(void);
void do_key3(void);
void do_int(void);


int main(int argc, const char *argv[])
{
	//key3
	do_key3();
	//pwm
	do_pwm();
	//int
	do_int();


	return 0;
}


void uart_putc(char c)
{	
	while(!(rUTRSTAT2&0X02));
	rUTXH2 = c;
	return;
}

void do_key3(void)
{
	//KEY3
	/* 设置GPA1控制器为UART模式 */
	rGPA1CON &= ~(0xff<<0);   	//把寄存器的bit0~7全部清零
	rGPA1CON |= 0X22<<0; 			//Rx,Tx
	/* 设置串口协议 */
	rULCON2 = 0x03; 			//0校验位 ,8数据位,1停止位
	rUCON2 = 0x05; 				//轮询模式
	/*
	 * 设置波特率:
	 *UART时钟信号源的值为:
	 *100Mhz= 100 000khz = 100 000 000hz
	 *本实验波特率值位115200,DIV_VAL = 100000000/(115200*16) -1 = 54.25 -1 = 53.25
	 *UBRDIVn = 53
	 *UFRACVALn/16 = 0.25 ----> UFRACVALn = 4
	 */
	rUBRDIV2 = 53; 				
	rUFBRACVAL2 = 4;
}	

void do_int(void)
{
	//INT
	/* 外设层次上,配置管脚工作模式 */
	rGPX1CON &= ~(0xf<<4); 	//设置为中断模式
	rGPX1CON |= (0xF<<4);

	rEXT_INT41CON &= ~(0X7<<4);
	rEXT_INT41CON |= (0X02<<4); 	//设置为下降沿触发

	rEXT_INT41_MASK &= ~(1<<1); 	//外设引脚使能中断,可以让中断发生
	/* GIC(通用中断控制器)层次上 */
	rICDISER1_CPU0 = rICDISER1_CPU0 | (1<<25); 	//使能当前中断
	rICDDCR |= (1<<0); 			//全局使能GIC 让所有中断可以通过GIC到达CPU
	rICCPMR_CPU0 |= (0xFF<<0); 	//设置中断优先级掩码级别为255
	/* CPU内核层次上 */
	rICCICR_CPU0 |= (1<<0); 		//CPU0的全局使能中断,所有中断都可以通过CPU接口到达内核
	
	rICDIPTR14_CPU0 = 0x01010101; //照抄,意义不明

	/* 发送状态判断 */	
	while(1)
	{
		uart_putc('c');
		delay1s();
	}
}

void do_irq(void) //参数中的void表示该函数不允许接受参数,理论上不写也可以,为了方便编译器通过,处于严谨考虑,还是要写上
{	
	int irq_num;
	irq_num = rICCIAR_CPU0&0x3FF; 	//获取中断号
	switch(irq_num) 
	{
	case 57:
		do_pwm_start();
        uart_putc('s');
		rEXT_INT41_PEND |= 1<<1; 	//清GPX1_1中断位
		rICDICPR1_CPU0 |= 1<<25; 	//清GIC GPX1_1中断位
		break;
	case 58:
		do_pwm_over();
        uart_putc('o');
		rEXT_INT41_PEND |= 1<<2; 	//清GPX1_2中断位
		rICDICPR1_CPU0 |= 1<<26; 	//清GIC GPX1_2中断位
		break;
	default:
		uart_putc('x');
		break;
	}
	
	rICCEOIR_CPU0 &= (~0x3FF);
	rICCEOIR_CPU0 |= irq_num; 	//结束中断 将处理完成的中断ID号写入该寄存器 表示相应的中断处理完成
}

void do_pwm_start(void)
{
	rGPD0CON &= ~(0xF); 	//GPD0_0设置为PWM模式
	rGPD0CON |= 0x02;

	rTCFG0 &= ~(0xFF); 		//TCFG0[7:0] 设置1分频为100
	rTCFG0 |= 0x64;

	rTCFG1 &= ~(0xF); 		//TCFG1[3:0]设置2分频为8
	rTCFG1 |= 0x3; 			

	rTCNTB0 = 200; 			//TCNTB0 设置3分频为200
	rTCMPB0 = 100;      	//占空比 = 100/200 = 0.5

    rTCON &= ~(0xF);    	//先用TCON 更新定时器timer0的 TCMPB0和TCMPB0值
    rTCON |= 0xA;
    rTCON &= ~(0xF);    	//再用TCON开启 定时器timer 0
    rTCON |= 0x9; 	
}

void do_pwm_over(void)
{
    rGPD0CON &= ~(0xF); 	//GPD0_0设置为PWM模式
	rGPD0CON |= 0x02;

	rTCFG0 &= ~(0xFF); 		//TCFG0[7:0] 设置1分频为100
	rTCFG0 |= 0x64;

	rTCFG1 &= ~(0xF); 		//TCFG1[3:0]设置2分频为8
	rTCFG1 |= 0x3; 			

	rTCNTB0 = 200; 			//TCNTB0 设置3分频为200
	rTCMPB0 = 100;      	//占空比 = 100/200 = 0.5

    rTCON &= ~(0xF);    	//先用TCON 更新定时器timer0的 TCMPB0和TCMPB0值
    rTCON |= 0xA;	
}


2. start.S 代码:

    .global  delay1s 
    .text     
    .global _start
_start:
		b		reset                          @0x00
		ldr		pc,_undefined_instruction    @0x04
		ldr		pc,_software_interrupt     
		ldr		pc,_prefetch_abort
		ldr		pc,_data_abort
		ldr		pc,_not_used
		ldr		pc,_irq                      @0x18
		ldr		pc,_fiq

_undefined_instruction: .word  _undefined_instruction
_software_interrupt:	.word  _software_interrupt
_prefetch_abort:		.word  _prefetch_abort
_data_abort:			.word  _data_abort
_not_used:				.word  _not_used
_irq:					.word  irq_handler 
_fiq:					.word  _fiq


irq_handler:
    sub  lr,lr,#4
    stmfd  sp!,{r0-r12,lr} 
    bl   do_irq
irq_handler_end:
    ldmfd  sp!,{r0-r12,pc}^ 



reset: 
	ldr	r0,=0x40008000      
	mcr	p15,0,r0,c12,c0,0		

init_stack:
	ldr		r0,stacktop         /*get stack top pointer*/

	/********svc mode stack********/
		mov		sp,r0
		sub		r0,#128*4          /*512 byte  for irq mode of stack*/
	/****irq mode stack**/
		msr		cpsr,#0xd2
		mov		sp,r0
		sub		r0,#128*4          /*512 byte  for irq mode of stack*/
	/***fiq mode stack***/
		msr 	cpsr,#0xd1
		mov		sp,r0
		sub		r0,#0
	/***abort mode stack***/
		msr		cpsr,#0xd7
		mov		sp,r0
		sub		r0,#0
	/***undefine mode stack***/
		msr		cpsr,#0xdb
		mov		sp,r0
		sub		r0,#0
   /*** sys mode and usr mode stack ***/
		msr		cpsr,#0x10
		mov		sp,r0             /*1024 byte  for user mode of stack*/

		b		main

delay1s:
     ldr      r4,=0xfffffff   
delay1s_loop:
     sub    r4,r4,#1
     cmp   r4,#0         
     bne    delay1s_loop
     mov   pc,lr	


	.align	4

	/****  swi_interrupt handler  ****/


stacktop:    .word 		stack+4*512

.data

stack:	
  .space  4*512
.end

3. map.lds 代码:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
	. = 0x40008000;  
	. = ALIGN(4);
	.text      :
	{
		start.o(.text)
		*(.text)
	}
	. = ALIGN(4);
    .data : 
	{ *(.data) }
    . = ALIGN(4);
    .bss :
     { *(.bss) }
}

4. Makefile 代码:

all:
	arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o start.o start.S
	arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o main.o main.c
	arm-none-linux-gnueabi-ld start.o main.o -Tmap.lds -o uart.elf
	arm-none-linux-gnueabi-objcopy -O binary  uart.elf uart.bin
	arm-none-linux-gnueabi-objdump -D uart.elf > uart.dis
clean:
	rm -rf *.bak start.o main.o uart.elf uart.bin uart.dis

5. 开发板效果展示:

6. 代码效果展示: