历史上的今天
返回首页

历史上的今天

今天是:2024年12月18日(星期三)

正在发生

2020年12月18日 | TQ210裸机编程(8)——PWM

2020-12-18 来源:eefocus

事实上,要使TQ210板子上的蜂鸣器发声是非常容易的,因为天嵌给TQ210的蜂鸣器为有源蜂鸣器,只要给蜂鸣器供电,蜂鸣器就会发出固定频率的声音。


TQ210板子上的蜂鸣器接在TOUT1引脚,只要给它高电平,蜂鸣器就会发声。


如下代码:


/* 配置GPD0[1]为输出 */

GPD0CON &= ~(0xF << 4);

GPD0CON |= 1 << 4;

/* GPD0[1]输出高电平即可使蜂鸣器发声 */

GPD0DAT |= 1 << 1;


S5PV210包含5个32位的脉宽调制定时器。这些定时器都可产生中断。每个定时器可选择输入时钟为PCLK或SCLK_PWM。


定时器的操作比较简单,下面列出操作步骤:


1、设置TCFG0寄存器:配置定时器的一级分频值


1、设置TCFG1寄存器:配置定时器的二级分频值


3、设置TCNTBn寄存器:递减计数器缓冲寄存器


3、设置TCMPBn寄存器:比较缓冲寄存器


4、设置TCON寄存器:


(1)手动更新on(执行后,CPU会把TCNTBn的值加载到递减计数器中)


(2)手动更新off、自动重载、启动定时器


当递减计数器的值减到和TCMPBn的值相等时,则翻转输出引脚极性;


当递减计数器的值减到0时,如果使能了定时器中断则产生中断,如果使能了自动重载则重载TCNTBn的值到递减计数器,开始重新计数


频率计算:


我之前的时钟配置为PCLK_PSYS=66MHz,这里就由它为定时器提供时钟源。


Timer Input Clock Frequency = PCLK / ( {prescaler value + 1} ) / {divider value}


我的配置为:prescaler value = 65


                      divider value = 8


Timer Input Clock Frequency = 66MHz / (65 + 1) / 8 = 125000

假设输出频率为n,则

TCNTB1 = 1125000 / n


比如输出1Hz,占空比为50%



TCNTB1 = 125000 / 1;

TCMPB1 = TCNTB1 / 2;


具体代码如下:


start.S


.global _start /* 声明一个全局的标号 */

_start:

 

bl clock_init

 

bl main /* 跳转到C函数去执行 */

 

halt:

b halt

 

clock.c


#define APLLCON0 *((volatile unsigned int *)0xE0100100)

#define MPLLCON *((volatile unsigned int *)0xE0100108)

#define EPLLCON0 *((volatile unsigned int *)0xE0100110)

#define VPLLCON *((volatile unsigned int *)0xE0100120)

#define CLK_SRC0 *((volatile unsigned int *)0xE0100200)

#define CLK_DIV0 *((volatile unsigned int *)0xE0100300)

#define CLK_DIV1 *((volatile unsigned int *)0xE0100304)

#define CLK_DIV2 *((volatile unsigned int *)0xE0100308)

#define CLK_DIV3 *((volatile unsigned int *)0xE010030C)

 

void clock_init()

{

/* 1、设置PLL_LOCK寄存器(这里使用默认值) */

/* 2、设置PLL_CON寄存器(使用芯片手册推荐的值) */

APLLCON0 = (1 << 0) | (3 << 8) | (125 << 16) | (1 << 31); /* FOUTAPLL = 1000MHz */

MPLLCON = (1 << 0) | (12 << 8) | (667 << 16) | (1 << 31); /* FOUTMPLL = 667MHz */

EPLLCON0 = (1 << 0) | (12 << 8) | (667 << 16) | (1 << 31); /* FOUTEPLL = 96MHz */

VPLLCON = (3 << 0) | (6 << 8) | (108 << 16) | (1 << 31); /* FOUTVPLL = 54MHz */

/* 3、选择PLL为时钟输出 */

/* MOUT_MSYS = SCLKAPLL = 1000MHz

** MOUT_DSYS = SCLKMPLL = 667MHz

** MOUT_PSYS = SCLKMPLL = 667MHz

*/

CLK_SRC0 = (1 << 0) | (1 << 4) | (1 << 8) | (1 << 12);

/* 4、设置系统时钟分频值 */

/* freq(ARMCLK) = MOUT_MSYS / (APLL_RATIO + 1) = 1000MHz / (0 + 1) = 1000MHz

** freq(HCLK_MSYS) = ARMCLK / (HCLK_MSYS_RATIO + 1) = 1000MHz / (4 + 1) = 200MHz

** freq(PCLK_MSYS) = HCLK_MSYS / (PCLK_MSYS_RATIO + 1) = 200MHz / (1 + 1) = 100MHz

** freq(HCLK_DSYS) = MOUT_DSYS / (HCLK_DSYS_RATIO + 1) = 667 / (3 + 1) = 166MHz

** freq(PCLK_DSYS) = HCLK_DSYS / (PCLK_DSYS_RATIO + 1) = 166 / (1 + 1) = 83MHz

** freq(HCLK_PSYS) = MOUT_PSYS / (HCLK_PSYS_RATIO + 1) = 667 / (4 + 1) = 133MHz

** freq(PCLK_PSYS) = HCLK_PSYS / (PCLK_PSYS_RATIO + 1) = 133 / (1 + 1) = 66MHz

*/

CLK_DIV0 = (0 << 0) | (4 << 8) | (1 << 12) | (3 << 16) | (1 << 20) | (4 << 24) | (1 << 28);

}


main.c


#define GPD0CON *((volatile unsigned int *)0xE02000A0)

#define GPD0DAT *((volatile unsigned int *)0xE02000A4)

 

#define TCFG0 *((volatile unsigned int *)0xE2500000)

#define TCFG1 *((volatile unsigned int *)0xE2500004)

#define TCON *((volatile unsigned int *)0xE2500008)

#define TCNTB1 *((volatile unsigned int *)0xE2500018)

#define TCMPB1 *((volatile unsigned int *)0xE250001C)

#define TCNTO1 *((volatile unsigned int *)0xE2500020)

 

int main()

{

#if 0

/* 配置GPD0[1]为输出 */

GPD0CON &= ~(0xF << 4);

GPD0CON |= 1 << 4;

/* GPD0[1]输出高电平即可使蜂鸣器发声 */

GPD0DAT |= 1 << 1;

#endif

/* 配置GPD0[1]为定时器1输出:TOUT1 */

GPD0CON &= ~(0xF << 4);

GPD0CON |= 2 << 4;

 

/*

** 配置定时器输入频率

** Timer Input Clock Frequency = PCLK / ( {prescaler value + 1} ) / {divider value} 

** = 66MHz / (65 + 1) / 8 = 125000

** 假设输出频率为n,则

** TCNTB1 = 1125000 / n

*/

TCFG0 = 65;

TCFG1 = 3 << 4;

 

/* 产生1Hz,占空比为50%的输出频率 */

TCNTB1 = 125000 / 1;

TCMPB1 = TCNTB1 / 2;

 

TCON = (1 << 9); /* 手动更新on */

TCON = (1 << 8) | (1 << 11); /* 启动定时器/手动更新off/自动重载 */

 

while (1);

return 0;

}


Makefile


beeper.bin: start.o clock.o main.o

arm-linux-ld -Ttext 0xD0020010 -o key.elf $^

arm-linux-objcopy -O binary key.elf $@

arm-linux-objdump -D key.elf > key.dis

%.o : %.c

arm-linux-gcc -c $< -o $@

%.o : %.S

arm-linux-gcc -c $< -o $@

clean:

rm *.o *.elf *.bin *.dis

推荐阅读

史海拾趣

风华邦科(FH-BK)公司的发展小趣事

广东粤翔航空服务有限公司(假设为FlyWin集团下的子公司)于2019年在珠海市金湾区成立,专注于航空咨询服务和航空器材租赁买卖。在成立初期,公司面临着航空服务市场的高度竞争和严格的行业监管。然而,凭借对市场的敏锐洞察和精准定位,粤翔航空通过提供专业的航空咨询和高效的器材租赁服务,逐渐在行业内站稳脚跟。公司不仅为多家航空公司提供了一站式的咨询服务,还成功促成了多笔航空器材的租赁交易,为公司后续的发展奠定了坚实基础。

EA Elektro-Automatik公司的发展小趣事

近年来,中国市场对EA Elektro-Automatik来说变得越来越重要。公司高层认识到了中国市场的巨大潜力和重要性,并制定了在中国市场继续投资和实现增长的明确计划。EA Elektro-Automatik的代表在多个场合与中国政府和行业领导进行交流和合作,努力拓展中国市场。目前,中国市场已经占据EA Elektro-Automatik全球业务的相当一部分份额,并有望在未来继续保持增长。

Continental公司的发展小趣事

Continental公司,即大陆集团,始建于1871年,总部位于德国的汉诺威市。最初,公司的主营业务是生产橡胶制品以及实心马车和自行车轮胎。在公司的早期历史中,一个关键的转折点出现在1882年,公司决定以猖獗的烈马作为品牌LOGO,象征着所生产的轮胎像强壮的烈马一般所向披靡。这一标志不仅赋予了轮胎强大的象征意义,还让人们开始将这些轮胎称为“马牌轮胎”。进入19世纪90年代,大陆集团成为了第一家生产充气马车和自行车胎的德国公司,这标志着其在轮胎制造技术上的重要突破。

Beck IPC GmbH公司的发展小趣事

Beck IPC始终坚持以研发和创新为核心驱动力。公司每年投入大量资金用于研发新技术和产品,并建立了完善的研发团队和体系。通过不断的技术创新和产品升级,Beck IPC始终保持着在嵌入式通讯和工业物联网领域的领先地位。同时,公司还积极参与国际标准制定和行业交流活动,为推动行业发展贡献自己的力量。

Advanced Thermal Solutions公司的发展小趣事

随着市场需求的不断增长,ATS意识到单纯的咨询服务已无法满足客户的全面需求。于是,公司决定转型为一家完整的散热解决方案提供商。ATS开始投入大量资源进行产品设计和制造,不断推出创新型的散热器产品。这些产品凭借高性能和卓越的质量,在市场中迅速脱颖而出,ATS也逐渐在电子产品热管理领域建立了领先地位。

Dell公司的发展小趣事

为了进一步扩大市场份额,ATS开始实施全球化战略。公司先后在北美、欧洲和亚洲等地设立了分公司或办事处,以便更好地服务全球客户。同时,ATS还积极参与国际展览和交流活动,与全球各地的合作伙伴建立紧密的合作关系。这些举措使ATS的产品和服务得以覆盖更广泛的地域,公司的知名度和影响力也不断提升。

问答坊 | AI 解惑

泊车用超声波测距仪的研制

摘要:本文论述了采用单片机技术研制成功的泊车用超声波测距仪的基本原理,测量计算方法,实现方案。采用软件校正,提高了测量精度和整机的可靠性。实际使用表明,极大的提高了泊车时的安全性。 关键词:超声波 测距 单片机 Development of Ultra ...…

查看全部问答>

5qzone_10天学会avr和c语言

5qzone_10天学会avr和c语言…

查看全部问答>

关于运行地址和加载地址的问题

在连接目标代码时,会提到运行地址和加载地址. 问:有什么区别吗? 如果程序是在flash里跑,是不是运行地址和加载地址是相同的? 如果程序是在ram里跑,但程序是存储在flash里的,是不是运行地址指向ram,而加载地址是指向flash? 没搞清楚! coldfire系 ...…

查看全部问答>

关于CE中断

DM9000片子中断线我接的是EINT0(GPH0:0),这个引脚同时也是Wake up中断,但是文档上说,PowerDown情况下是Wake Up中断,正常状态下是普通中断。我在BSPIntrInit()中上拉该引脚后,在后面不知道被哪里下拉了,查BSP没发现其他哪里使用GPH0。 怎 ...…

查看全部问答>

CreateFile调用 IIC驱动问题

再EVC下用CreateFile()打开IIC设备成功返回句柄,用返回的句柄调用WriteFile(),WriteFile的返回值wRetSize为0;GetLastError返回的也为0 代码如下: hT2C = CreateFile(TEXT(\"I2C1:\"),               &nbs ...…

查看全部问答>

设备打开错误求助

别人做的USB转串口驱动没源码,一共六个虚拟COM:COM4-COM9,COM5-COM9打开没问题,COM4打开的时候: unable to open COM4:,ERROR NO,=55 在PB5.0的帮助文档上查到55号错误是下面这样说的 55     illegal line start symbol ...…

查看全部问答>

我往STC89LE516AD单片机烧程式时,得烧上20次才进去一两次

每次烧程式,不停的给单片机上电复位,可就是不进去,一二十次才进去一两次,不知道是什么原因,按理说,有时能烧录,所以电路因该没有问题,但大多时候还是显示连接失败,有那位高人知道这是什么原因!…

查看全部问答>

本人因为学习需要 购2410二手开发板一块 联系qq:42281797 tel:13554742552

本人因为学习需要 购2410二手开发板一块 联系qq:42281797 tel:13554742552 欢迎联系 谢谢…

查看全部问答>

请教关于fft的问题。

本帖最后由 dontium 于 2015-1-23 13:39 编辑 各位老师好,我想用2812做一个fft的程序,但不知如何下手,我想向各位请教一下,应该如何利用TI公司自带的fft库函数来实现,我现在把需要计算的小数值存放在外部ram中,不知道应该怎么处理,而且我知 ...…

查看全部问答>