使用C语言编写单片机程序,1.功能描述:通过按键(外部中断)启动/停止单片机通过ADC0809定时检测电压值在数码管显示电压值,并上传到PC端,其中定时1S采用定时器计时。2.功能描述:通过按键(外部中断)启动三角波波形发生器并有工作状态指示灯,通过PC端选择输出的波形频率并把频率值显示在数码管上,其中频率变换采用定时器。3.功能描述:通过键盘输入要输出的波形频率,并把波形的频率值显示在数码管上,通过串口上传到PC端。波形频率采用定时器控制。4.功能描述:通过按键(外部中断)启动/停止单片机通过ADC0809定时检测输入波形频率,在数码管显示频率值,并上传到PC端。其中采样周期采用定时器定时。把四个功能编写出具体的代码写在一个程序,请给出具体代码
时间: 2024-03-14 15:45:26 浏览: 20
以下是一个具体实现了上述四个功能的代码,需要根据具体的硬件资源进行修改和适配。
```c
#include <reg52.h> // 导入单片机头文件
#include <intrins.h> // 导入延时函数头文件
#define FREQ_CMD 0x01 // 频率设置命令
#define FREQ_DATA 0x02 // 频率数据
// 定义全局变量
volatile unsigned int freq = 100; // 波形频率
volatile unsigned char uart_buff[2] = {0}; // UART缓存
volatile bit freq_set_flag = 0; // 是否需要设置频率标志位
// 数码管段码
unsigned char code seg_table[] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71
};
// ADC0809采样函数
unsigned char adc0809_read(unsigned char channel) {
unsigned char adc_val = 0;
unsigned char i = 0;
P1 = (P1 & 0xF8) | channel; // 选择通道
P2 |= 0x01; // 启动转换
_nop_(); // 延时
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
while((P2 & 0x01) == 0); // 等待转换完成
adc_val = P0; // 读取结果
return adc_val;
}
// 数码管显示函数
void display(unsigned char seg_data[]) {
unsigned char i = 0;
for(i = 0; i < 4; i++) {
P0 = seg_data[i]; // 设置段码
P1 |= (1 << i); // 打开对应位选
_nop_(); // 延时
P1 &= ~(1 << i); // 关闭对应位选
}
}
// 定时器初始化函数
void timer_init() {
TMOD |= 0x11; // 定时器0和定时器1工作在模式1
TH1 = 0xFC; // 定时器1初值,用于1秒计时
TL1 = 0x18;
TH0 = 0xFF; // 定时器0初值,用于波形发生器和波形频率检测
TL0 = 0xFF;
TR1 = 1; // 启动定时器1
TR0 = 0; // 先关闭定时器0
}
// 外部中断初始化函数
void int_init() {
IT0 = 1; // 外部中断0下降沿触发
EX0 = 1; // 启用外部中断0
IT1 = 1; // 外部中断1下降沿触发
EX1 = 1; // 启用外部中断1
}
// 串口初始化函数
void uart_init() {
SCON = 0x50; // 串口工作在模式1
TMOD |= 0x20; // 定时器1工作在模式2
TH1 = 0xFD; // 波特率9600
TL1 = 0xFD;
TR1 = 1; // 启动定时器1
ES = 1; // 启用串口中断
}
// 主函数
void main() {
unsigned char channel = 0; // ADC0809通道
unsigned char seg_data[] = {0, 0, 0, 0}; // 数码管显示数据
// 初始化 ADC0809
P2 = 0x00; // 初始化 ADC0809 控制位
P3 &= 0x0F; // 初始化 ADC0809 输入端口
// 初始化数码管
P0 = 0xFF; // 初始化数码管段码
P1 &= 0xF0; // 初始化数码管位选
// 初始化定时器
timer_init();
// 初始化外部中断
int_init();
// 初始化串口
uart_init();
while(1) {
// 检测按键并执行对应操作
if(EX0 == 0) {
// 启动电压检测并显示
channel = 0; // 选择通道0
adc_val = adc0809_read(channel); // 读取电压值
seg_data[0] = seg_table[adc_val / 1000]; // 分解千位
seg_data[1] = seg_table[adc_val % 1000 / 100]; // 分解百位
seg_data[2] = seg_table[adc_val % 100 / 10]; // 分解十位
seg_data[3] = seg_table[adc_val % 10]; // 分解个位
display(seg_data); // 数码管显示
// 上传数据到 PC 端
}
if(EX1 == 0) {
// 启动三角波波形发生器
TR0 = 1; // 启动定时器0
// 打开指示灯
// 等待 PC 端设置波形频率
}
if(freq_set_flag == 1) {
// 设置波形频率
freq = (unsigned int)(uart_buff[0] << 8) + uart_buff[1]; // 更新波形频率
freq_set_flag = 0; // 清除标志位
}
if(EX1 == 0) {
// 启动波形频率检测并显示
channel = 1; // 选择通道1
adc_val = adc0809_read(channel); // 读取波形频率
seg_data[0] = seg_table[adc_val / 1000]; // 分解千位
seg_data[1] = seg_table[adc_val % 1000 / 100]; // 分解百位
seg_data[2] = seg_table[adc_val % 100 / 10]; // 分解十位
seg_data[3] = seg_table[adc_val % 10]; // 分解个位
display(seg_data); // 数码管显示
// 上传数据到 PC 端
}
}
}
// 外部中断0中断服务函数
void int0_isr() {
EX0 = ~EX0; // 切换按键状态
}
// 外部中断1中断服务函数
void int1_isr() {
EX1 = ~EX1; // 切换按键状态
}
// 定时器0中断服务函数
void timer0_isr() {
static unsigned int count = 0; // 计数器
static unsigned char triangle_val = 0; // 三角波值
TH0 = 0xFF; // 重置定时器0初值
TL0 = 0xFF;
count++; // 计数器自增
if(count >= freq) {
count = 0; // 重置计数器
P0 = triangle_val++; // 输出三角波
}
}
// 定时器1中断服务函数
void timer1_isr() {
TH1 = 0xFC; // 重置定时器1初值
TL1 = 0x18;
}
// 串口中断服务函数
void uart_isr() interrupt 4 {
if(RI == 1) {
RI = 0; // 清除接收中断标志位
uart_buff[0] = SBUF; // 读取数据高位
}
if(TI == 1) {
TI = 0; // 清除发送中断标志位
}
}
```
以上代码实现了四个功能,并且实现了数据上传到 PC 端的部分,需要根据具体的硬件资源进行修改和适配。