第一个程序,让你的板子唱国歌(败笔)

本文作者分享了一次尝试让ARM板子通过蜂鸣器唱国歌的实验过程,旨在激发读者的兴趣。通过分析C51的唱国歌程序并尝试在ARM板上实现,作者遇到了包括编译器不支持浮点除法等问题。虽然最终实验失败,但过程中的思路和错误分析对理解硬件控制和ARM编程有一定帮助。
摘要由CSDN通过智能技术生成

虽然是败笔,但是文中基本上介绍了一个小应用实现及问题分析的全过程,希望能够对你有帮助,大胆贴出!毕竟这篇文章写了好久。。。额,写文章的人伤不起啊伤不起。。。


学生时代总会有这么一句笑话:“XXX!去,给我蹲政教处门口唱国歌!”

      一直在思索第一个例子用什么,才能引起学生的兴趣,点亮板子的LED?貌似很无聊啊,你也不能拿着给同学炫耀,毫无吸引力,那么就索性用这个例子吧,顺便也抒发一下我对祖国的热爱。让我们的板子唱起国歌来!

      前记:在这篇文章之前,我并没有做过类似的实验,所以我们站在同一个起跑线上,千万不要抱怨别人比你厉害是因为他比你聪明。如果试验成功,板子真的这么唱歌了,像我这么笨的人都做到了,你没有理由做不到,这篇文章让你找回自信。

      首先要贴出来一篇参考文章,是基于C51的唱国歌的例子,做人要实在,我不想把它说成是我原创的,因为我也没学过C51,呵呵,但是我会举一反三。因为ARM板裸奔跟写C51的程序差不多,虽然扼杀了它的处理能力(本该是跑系统的),但是要练习对硬件的操控能力和做接口实验,这些是必须的。下边是文章内容:

蜂鸣器使用在很多的场合,他一般用来发出报警或者提示的声音,是一种常用的电子器件,这里我给大家 简单的介绍一下用单片机驱动蜂鸣器的方法, 蜂鸣器有二种 1.本身带有驱动电路, 5v,9v,12v 超电压使用, 分 声音沙哑失真。2.象 call 机,喇叭一样,用软件驱动。频率控制音调,时间控制音量大小,第一种蜂鸣器 一般都有一个固定的频率参数也就是他他发出的声音是不能变化的,就象食堂用的打卡器一样,卡一贴近 就发出都的一声。第 2 种就不同了用单片机驱动第 2 种蜂鸣器后还可以使他演 奏出美妙的音乐,我们只需 要用简单的程序就可以控制单蜂鸣器所奏的频率,也就控制了音调。
 c51程序实例: 单片机驱动蜂鸣器演奏中华人民共和国国歌的前 4 节的 c51 程序: 

#include <REG52.h> 
sbit BUZ=P2^6; //蜂鸣器接单片机的p2.6 电路很简单。
 unsigned int hzs[]={131,147,165,175,196,220,247,262,294,330,349,392,440,494,523,587,659,698,784,880,988,1047,1175,131 9,1397,1568,1760,1976};//标准音调频率 
char dots[]={8,28,10,12,12,13,28,28,12,28,10,28,8,12,12,12,10,28,28,8,28,5,5,5,5,5,5,8,'#'};//频率控制数组
 void delay(unsigned int u) //延时 
{ 
while(u--); 
} 
void play_hz(unsigned int u) { 
unsigned int i=u; 
while(i--){
 		BUZ=0; 
BUZ=1;
 delay(18432/u-24); 
} 
} 
void play_sound(int i) {
 if(i<28) 
play_hz(hzs[i-1]); 
else 
delay(500); } 
void main(void) //主程序开始 
{ 
while(1){
 int i=0; 
while(dots[i]!='#') 
play_sound(dots[i++]); 
delay(20000);
 } 
} //播放音乐 
音调与频率的关系: 
C:261.6256
D:293.6648 
E:329.6276 
F:349.2282 
G:391.9954 
A:440 
B:493.8833 
每个 8 度频率加倍,如 A 的高 8 度是 880HZ,再高 8 度是 1760HZ。 反之,A 的低 8 度是 220HZ,再低 8 度是 110HZ。

完文章,我们来做ARM下的实现:

我想当你看完文章,应该有些思路了吧,不知道我们的思路一样不一样,也不知道这个实验可否成功,让我们一起去探索一下》》》》》》

      我的思路是这样的:蜂鸣器的控制应该和LED的控制是一样的,根据电路设计,在对应的控制寄存器中的对应控制位写1(或者0)他就唱,相反,他就不唱。而不同的音调就是通过频率来控制的,而频率就是一个动作周期性变化的次数,上边的程序已经写得非常到位,简洁有力,通过while循环和时延控制频率。理论上我们只用作少量改动就可以使用。而这些改动就要看我们自己的板子的设计了,我的是TQ2440,虽不知你的是不是,但是只要你可以在你的板子上迁移成功,证明你已经提升了,OK,here we go。


      先看一下TQ2440 的 buzzer相关的电路(在TQ2440底板原理图里):


在C语言中,编写一个主控板控制另一个板子程序通常涉及到硬件通信协议,比如串口通信(RS-232/RS-485)、I2C、SPI、CAN或网络通信(如TCP/IP)。由于硬件通信的具体实现依赖于所使用微控制器的硬件规格和外部硬件接口,这里提供一个基于串口通信的简单示例。 假设主控板是一台计算机,而被控制的板子是一块带有微控制器的电路板。主控板通过串口发送命令,被控制的板子接收命令并执行相应的动作。 以下是一个非常基础的示例,展示了如何在主控板上使用C语言通过串口发送命令: ```c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> int main() { // 打开串口设备 int serial_port = open("/dev/ttyUSB0", O_RDWR); // 配置串口 struct termios tty; memset(&tty, 0, sizeof(tty)); if (tcgetattr(serial_port, &tty) != 0) { printf("Error %i from tcgetattr", errno); return 1; } // 设置输入输出波特率 cfsetispeed(&tty, B9600); cfsetospeed(&tty, B9600); // 设置串口属性 tty.c_cflag &= ~PARENB; // 清除校验位 tty.c_cflag &= ~CSTOPB; // 使用一个停止位 tty.c_cflag &= ~CSIZE; // 清除数据位掩码 tty.c_cflag |= CS8; // 8位数据位 tty.c_cflag &= ~CRTSCTS; // 无硬件流控制 tty.c_cflag |= CREAD | CLOCAL; // 打开接收器,忽略modem控制线 tty.c_lflag &= ~ICANON; tty.c_lflag &= ~ECHO; // 关闭回显 tty.c_lflag &= ~ECHOE; // 关闭回显擦除 tty.c_lflag &= ~ECHONL; // 关闭换行回显 tty.c_lflag &= ~ISIG; // 关闭信号字符 tty.c_iflag &= ~(IXON | IXOFF | IXANY); // 关闭软件流控制 tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // 禁用特殊处理 tty.c_oflag &= ~OPOST; // 关闭实现定义的输出处理 tty.c_oflag &= ~ONLCR; // 关闭换行转回车换行 tty.c_cc[VTIME] = 10; // 等待数据的超时时间(十分之一秒) tty.c_cc[VMIN] = 0; // 最小接收字符为0 // 保存串口配置 if (tcsetattr(serial_port, TCSANOW, &tty) != 0) { printf("Error %i from tcsetattr", errno); return 1; } // 写入数据到串口 char *write_buf = "Hello, controlled board!\n"; write(serial_port, write_buf, strlen(write_buf)); // 关闭串口 close(serial_port); return 0; } ``` 在被控制板子的微控制器端,你需要编写相应的程序来监听串口,接收来自主控板的命令,并根据命令控制板上的硬件。这通常涉及到中断服务程序、数据接收缓冲区管理和硬件操作逻辑。 被控制板子端的伪代码大致如下: ```c // 初始化串口硬件 initializeSerialPort(); // 串口中断服务程序(伪代码) void serialInterruptHandler() { if (serialPortHasData()) { char receivedCommand[COMMAND_MAX_SIZE]; int commandLength = readSerialPort(receivedCommand, sizeof(receivedCommand)); handleCommand(receivedCommand, commandLength); } } // 处理接收到的命令(伪代码) void handleCommand(char* command, int length) { if (strcmp(command, "Hello, controlled board!\n") == 0) { // 执行相应的硬件控制代码 controlHardware(); } } // 主循环(伪代码) int main() { while (1) { // 执行其他任务 } return 0; } ``` 在实际的项目中,你需要根据具体的硬件手册和通信协议来编写详细的代码。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值