历史上的今天
今天是:2024年10月12日(星期六)
2018年10月12日 | Tiny210裸机PWM控制蜂鸣器
2018-10-12 来源:eefocus
start.S源码:
.global _start
_start:
ldr sp, =0xD0030000 // 初始化栈,因为后面要调用C函数
bl clock_init // 初始化时钟
bl ddr_init // 初始化内存
bl nand_init // 初始化NAND
ldr r0, =0x36000000 // 要拷贝到DDR中的位置
ldr r1, =0x0 // 从NAND的0地址开始拷贝
ldr r2, =bss_start // BSS段的开始地址
sub r2,r2,r0 // 要拷贝的大小
bl nand_read // 拷贝数据
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
ldreq pc, =on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
ldr pc, =on_ddr
on_ddr:
ldr sp, =0x3f000000 // 重新初始化栈,指向内存
ldr pc, =main
=====================================================================
timer.c源码:
#define GPD0CON (*(volatile unsigned int *)0xE02000A0)
#define TCFG0 (*(volatile unsigned int *)0xE2500000)
#define TCFG1 (*(volatile unsigned int *)0xE2500004)
#define TCON (*(volatile unsigned int *)0xE2500008)
#define TCNTB0 (*(volatile unsigned int *)0xE250000C)
#define TCMPB0 (*(volatile unsigned int *)0xE2500010)
#define TCNTO0 (*(volatile unsigned int *)0xE2500014)
void pwm_init(void)
{
// 配置为GPD0_0用于PWM输出
GPD0CON |= (0x2 << 0); // TOUT_0
}
void timer0_init(void)
{
// 设置时钟源
// Timer0 input clock Frequency = 66700000 / ( {prescaler + 1} ) / {divider value}
// = 66700000 / (1+1) / 1
// = 33350000( 即1s计数33350000次 )
TCFG0 &= ~(0xff);
TCFG0 |= 1; // Prescaler = 1
TCFG1 &= ~0xf; // 0000 = 1/1
// 设置TCNTB0(即PWM的频率)
TCNTB0 = 33350; // PWM的频率为1KHz
// 设置TCMPB0(即PWM的占空比)
TCMPB0 = 16675; // 占空比为50%
TCON &= ~(1<<2); // 不进行电平反转(即引脚初始值为0)
TCON |= (1<<3); // auto-reload
}
void pwm_start(void)
{
TCON |= (1<<1); // set manual update
TCON |= (1<<0); // start timer 0
TCON &= ~(1<<1); // clean manual update
}
void pwm_stop(void)
{
TCON &= ~(1<<0); // stop timer 0
}
=====================================================================
command.c源码:
#include "lib.h"
#include "nand.h"
#include "timer.h"
int help(int argc, char * argv[])
{
wy_printf("do_command 《%s》 \n", argv[0]); //"《"实际为"<"
wy_printf("help message: \n");
wy_printf("md - memory dispaly\n");
wy_printf("mw - memory write\n");
wy_printf("nand read - nand read sdram_addr nand_addr size\n");
wy_printf("nand write - nand write sdram_addr nand_addr size\n");
wy_printf("pwm on - turn on buzzer \n");
wy_printf("pwm off - turn off buzzer\n");
return 0;
}
int md(int argc, char * argv[])
{
unsigned long *p = (unsigned long *)0;
int i, j;
wy_printf("do_command 《%s》 \n", argv[0]);
if (argc <= 1) {
wy_printf ("Usage:\n%s\n", "md address");
return 1;
}
if (argc >= 2)
p = (unsigned long *)atoi(argv[1]);
for (j = 0; j < 16; j++)
{
wy_printf("%x: ", p);
for (i = 0; i < 4; i++)
wy_printf("%x ", *p++);
wy_printf("\n");
}
return 0;
}
int mw(int argc, char * argv[])
{
unsigned long *p = (unsigned long *)0;
int v = 0;
wy_printf("do_command 《%s》 \n", argv[0]);//"《"实际为"<"
if (argc <= 2) {
wy_printf ("Usage:\n%s\n", "md address data");
return 1;
}
if (argc >= 2)
p = (unsigned long *)atoi(argv[1]);
if (argc >= 3)
v = atoi(argv[2]);
*p = v;
return 0;
}
int nand(int argc, char *argv[])
{
int nand_addr, sdram_addr;
unsigned int size;
if (argc < 5)
{
wy_printf("nand read sdram_addr nand_addr size\n");
wy_printf("nand write sdram_addr nand_addr size\n");
return 0;
}
sdram_addr = atoi(argv[2]);
nand_addr = atoi(argv[3]);
size = atoi(argv[4]);
wy_printf("do_command 《%s》 \n", argv[0]);
wy_printf("sdram 0x%x, nand 0x%x, size 0x%x\n", sdram_addr, nand_addr, size);
if (strcmp(argv[1], "read") == 0)
nand_read((unsigned char *)sdram_addr, nand_addr, size);
if (strcmp(argv[1], "write") == 0)
nand_write(sdram_addr, nand_addr, size);
wy_printf("nand %s finished!\n", argv[1]);
return 0;
}
int pwm(int argc, char *argv[])
{
pwm_init();
if (argc < 2)
{
wy_printf("pwm on - turn on buzzer \n");
wy_printf("pwm off - turn on buzzer\n");
return 0;
}
if (strcmp(argv[1], "on") == 0)
pwm_start();
if (strcmp(argv[1], "off") == 0)
pwm_stop();
return 0;
}
void run_command(int argc, char * argv[])
{
if (strcmp(argv[0], "help") == 0)
{
help(argc, argv);
return;
}
if (strcmp(argv[0], "md") == 0)
{
md(argc, argv);
return;
}
if (strcmp(argv[0], "mw") == 0)
{
mw(argc, argv);
return;
}
if (strcmp(argv[0], "pwm") == 0)
{
pwm(argc, argv);
return;
}
if (strcmp(argv[0], "nand") == 0)
nand(argc, argv);
if(argc >= 1)
wy_printf("Unknown command '%s' - try 'help' \n",argv[0]);
return;
}
=====================================================================
main.c源码:
#include "command.h"
#include "clock.h"
#include "led.h"
#include "uart.h"
#include "lib.h"
#include "nand.h"
#define CFG_PROMPT "WY_BOOT # " // Monitor Command Prompt
#define CFG_CBSIZE 256 // Console I/O Buffer Size
char *argv[10];
int readline (const char *const prompt)
{
char console_buffer[CFG_CBSIZE]; // console I/O buffer
char *buf = console_buffer;
int argc = 0;
int state = 0;
//puts(prompt);
wy_printf("%s",prompt);
gets(console_buffer);
while (*buf)
{
if (*buf != ' ' && state == 0)
{
argv[argc++] = buf;
state = 1;
}
if (*buf == ' ' && state == 1)
{
*buf = '\0';
state = 0;
}
buf++;
}
return argc;
}
void message(void)
{
wy_printf("\nThis bootloader support some command to test peripheral:\n");
wy_printf("Such as: LCD, IIS, BUZZER \n");
wy_printf("Try 'help' to learn them \n\n");
}
int main(void)
{
char buf[6];
int argc = 0;
int i = 0;
led_init(); // 设置对应管脚为输出
uart_init(); // 初始化UART0
nand_read_id(buf);
timer0_init(); // 初始化定时器0,用于PWM输出,延时1S
wy_printf("\n**********************************************************\n");
wy_printf(" wy_bootloader\n");
wy_printf(" vars: %d \n",2012);
wy_printf(" nand id:");
putchar_hex(buf[0]);
putchar_hex(buf[1]);
putchar_hex(buf[2]);
putchar_hex(buf[3]);
putchar_hex(buf[4]);
wy_printf("\n**********************************************************\n");
while (1)
{
argc = readline (CFG_PROMPT);
if(argc == 0 && i ==0)
{
message();
i=1;
}
run_command(argc, argv);
}
return 0;
}
====================================================================
Makefile文件:
uart.bin:start.s main.c uart.c clock.c led.c lib.c command.c nand.c mem_setup.S timer.c
arm-linux-gcc -nostdlib -c start.s -o start.o
arm-linux-gcc -nostdlib -c main.c -o main.o
arm-linux-gcc -nostdlib -c uart.c -o uart.o
arm-linux-gcc -nostdlib -c lib.c -o lib.o
arm-linux-gcc -nostdlib -c clock.c -o clock.o
arm-linux-gcc -nostdlib -c led.c -o led.o
arm-linux-gcc -nostdlib -c command.c -o command.o
arm-linux-gcc -nostdlib -c nand.c -o nand.o
arm-linux-gcc -nostdlib -c timer.c -o timer.o
arm-linux-gcc -nostdlib -c mem_setup.S -o mem_setup.o
arm-linux-ld -T bootloader.lds start.o main.o uart.o lib.o clock.o led.o command.o nand.o mem_setup.o timer.o -o uart_elf
arm-linux-objcopy -O binary -S uart_elf uart.bin
clean:
rm -rf *.o *.bin uart_elf *.dis
====================================================================
bootloader.lds链接文件:
SECTIONS {
. = 0x36000010;
.text : {
* (.text)
}
. = ALIGN(4);
.rodata : {
* (.rodata)
}
. = ALIGN(4);
.data : {
* (.data)
}
. = ALIGN(4);
bss_start = .;
.bss : { *(.bss) *(COMMON) }
bss_end = .;
}
===================================================================
一,定时器用于PWM输出(驱动蜂鸣器):
下面,先介绍下定时器的几个关键的寄存器吧:
问:大家都知道,定时器的实现,其实就是一个计数的过程(从0家到一个数字或从一个数字减到0),那么这个数字从哪里来呢?
答:从寄存器TCNTBx中获得,当我们编程时,写入一个数组到该寄存器,然后通过手动装载或自动装载,就会把该寄存器的值用于"一个数字"了。
问:PWM波形是高低电平交替出现的,那么定时器输出的电平什么时候翻转呢?
答:这个情况和TCMPBx寄存器中的值有关系,当计数器中的值("一个数字")减到(或加到)和TCMPBx寄存器中的值相等时,电平翻转。
本来想多说点的,但是实在是没什么可说的,直接上部分代码吧:
void timer0_init(void)
{
// 设置时钟源
// Timer0 input clock Frequency = 66700000 / ( {prescaler + 1} ) / {divider value}
// = 66700000 / (1+1) / 1
// = 33350000( 即1s计数33350000次 )
TCFG0 &= ~(0xff);
TCFG0 |= 1; // Prescaler = 1
TCFG1 &= ~0xf; // 0000 = 1/1
// 设置TCNTB0(即PWM的频率)
TCNTB0 = 33350; // PWM的频率为1KHz
// 设置TCMPB0(即PWM的占空比)
TCMPB0 = 16675; // 占空比为50%
TCON &= ~(1<<2); // 不进行电平反转(即引脚初始值为0)
TCON |= (1<<3); // auto-reload
}
以上是定时器的初始化代码,关于定时器用于PWM输出的代码我以经共享在了"Tiny210学习日记_代码"目录下了,名为"14_pwm"。请大家自己阅读,十分简单。
测试方法:(在终端输入命令)
pwm on (蜂鸣器响)
pwm off (蜂鸣器不响)
史海拾趣
|
5月19日,巴黎现代艺术博物馆的5幅分别出自毕加索、马蒂斯、布拉克、莱热以及莫迪利亚尼之手的世界级名画一夜之间被秘密盗走。这5幅名画总价值5亿欧元(有媒体更正为1亿欧元),目前警方已开始着手调查。 据法国媒体报道,巴黎现代艺术博物馆 ...… 查看全部问答> |
|
先来说说规格: 开机需要两个LOGO,分别是一个静态LOGO用来显示公司名字,一个是动态LOGO用来显示CE的加载过程。 第一个应该比较好弄,在bootloader中OENPlatformInit中初始化屏完毕后,将要显示的图片数据复制到显存中即可。 问题是第二个, ...… 查看全部问答> |
|
如题,我手头的NANDFLASH驱动版本太老,在内核加新功能时总是:Failed to add the PCI NAND Flash Driver (SDNPCID) feature (SYSGEN_MSFLASH) to the platform.,哪位大哥有写好的给小弟发一份 我用的是WINCE4.2 慧通(www.witech.com.cn)24 ...… 查看全部问答> |
|
vxWorks compress rom的解压缩速度问题,MIPS 24KEC CACHE 4路组相连 手上在做一个用MIPS32 24KEC的项目,CACHE这块似乎我一直没调对,后边都起的差不多了但是这里仍然有问题 体现如下:无论在config0最后3bit写0,2,3,7 就是写透关闭写回还有一个是UNCACHE 加速~不是很明白~总之几个CACH ...… 查看全部问答> |
|
如何用\WINCE500\PUBLIC\SERVERS\SDK\SAMPLES下的ftpd文件夹做一个FTP服务器的exe呢(用EVC来实现)? 如何用\\WINCE500\\PUBLIC\\SERVERS\\SDK\\SAMPLES下的ftpd文件夹里的那些文件做一个FTP服务器的exe呢(用EVC来实现)? 做出一个exe文件来,一点击就相当与建立了一个FTP服务器. 请高手给出思路,多谢! … 查看全部问答> |
|
协议栈中UART有两种模式: 1、中断 2、DMA对于这两种模式具体运用在哪一步,纠结了很久.通过UART配置结构: typedef struct { uint8 *rxBuf; uint8 rxHead; uint8 rxTail; uint8 rxMax; &nb ...… 查看全部问答> |




