改进程序实现与上位机的串口通讯
时间: 2024-03-09 18:49:18 浏览: 74
以下是改进后的电子琴程序,可以通过串口与上位机通讯:
```c
#include <reg52.h> // 引入51单片机头文件
#include <stdio.h> // 引入标准输入输出库
#include <string.h> // 引入字符串库
#include <stdlib.h> // 引入标准库
#include <intrins.h> // 引入位操作库
// 定义按键及其音符
#define KEY1 P3_2
#define KEY2 P3_3
#define KEY3 P3_4
#define KEY4 P3_5
#define NOTE1 0x02
#define NOTE2 0x04
#define NOTE3 0x06
#define NOTE4 0x08
// 定义串口通讯参数
#define BAUDRATE 9600
#define TIMER_1MS_RELOAD_VALUE (65536 - FOSC / 12 / 1000) // 定时器重载值,用于实现1ms的定时
// 定义全局变量
volatile unsigned char g_note; // 全局变量,存储当前播放的音符
// 延时函数
void delay(unsigned int t)
{
unsigned int i, j;
for (i = 0; i < t; i++)
{
for (j = 0; j < 125; j++)
{
;
}
}
}
// 播放音符
void play(unsigned char note)
{
unsigned int t;
switch (note)
{
case NOTE1:
t = 100;
break;
case NOTE2:
t = 200;
break;
case NOTE3:
t = 300;
break;
case NOTE4:
t = 400;
break;
default:
t = 0;
break;
}
P1 = 0x00; // 发出声音
delay(t);
P1 = 0xFF; // 停止声音
delay(50);
}
// 定时器1中断,用于实现1ms的定时
void timer1_isr() interrupt 3
{
static unsigned int counter = 0;
TH1 = TIMER_1MS_RELOAD_VALUE >> 8;
TL1 = TIMER_1MS_RELOAD_VALUE & 0xFF;
if (++counter >= 10) // 每10ms检查一次串口接收
{
counter = 0;
if (RI)
{
unsigned char ch = SBUF;
if (ch >= '1' && ch <= '4')
{
g_note = ch - '0';
}
RI = 0;
}
}
}
// 主函数
void main()
{
unsigned char str[20]; // 存储输出到串口的字符串
unsigned int freq; // 存储当前音符的频率
// 初始化串口
TMOD |= 0x20; // 定时器1工作在方式2,8位自动重装载
TH1 = TIMER_1MS_RELOAD_VALUE >> 8;
TL1 = TIMER_1MS_RELOAD_VALUE & 0xFF;
PCON |= 0x80; // 波特率倍增(SMOD=1)
SCON = 0x50;
TR1 = 1;
ES = 1; // 开启串口中断
EA = 1; // 全局中断开关
while (1)
{
switch (g_note)
{
case 1:
freq = 262;
break;
case 2:
freq = 294;
break;
case 3:
freq = 330;
break;
case 4:
freq = 349;
break;
default:
freq = 0;
break;
}
if (freq) // 如果有音符需要播放
{
sprintf(str, "Note %d, Freq %dHz\r\n", g_note, freq);
printf("%s", str); // 输出到串口
g_note = 0;
play(freq);
}
}
}
```
这个程序增加了串口通讯功能,可以通过串口接收上位机发送的音符选择指令,并输出当前播放的音符及其频率。在程序中,`g_note` 是一个全局变量,用于存储当前需要播放的音符。每隔10ms,程序会检查串口是否有数据,如果有数据,就读取数据并解析成对应的音符,存储到 `g_note` 中。然后根据 `g_note` 的值,计算出对应的频率,播放对应的音符,并通过串口输出当前播放的音符及其频率。注意,在程序中需要开启串口中断,并在中断函数中读取串口数据。
同时,为了实现1ms的定时,程序使用了定时器1,并开启了定时器1中断。在中断函数中,每次重置定时器1的计数器,并计数10次,即1ms,然后检查串口是否有数据。
阅读全文