用C语言完成51单片机程序 上位机: (1) 滑动电阻产生模拟电压输入,利用A/D转换芯片,输出数字量:并 向下位机发送A/D转换的数字量。 下位机: (1) 接收上位机发送的数字量: (2) 根据上位机的数字量产生一定频率的模拟方波(上位机的数字量决 定方波的频率) ; (3)方波信号作为外部计数脉冲输入,产生中断,中断次数传回上位机
时间: 2024-03-08 09:46:07 浏览: 143
以下是一个基本的51单片机程序,完成了上位机和下位机之间的通信以及基本的功能实现。具体的实现方式可能因为硬件不同而有所不同,需要根据具体情况进行调整。
```c
#include <reg52.h>
// 定义串口通信参数
#define BAUDRATE 9600
#define TIMER_VALUE (65536 - FOSC / 12 / BAUDRATE)
// 定义A/D转换引脚
sbit ADCIN = P1^0;
// 定义计数器引脚
sbit COUNTER = P1^1;
// 定义变量
unsigned int ad_value; // 存储A/D转换的数字量
unsigned int counter_value; // 存储计数器的中断次数
// 定义函数
void init_serial(); // 初始化串口通信
void init_adc(); // 初始化A/D转换
void init_timer(); // 初始化定时器
void send_value(unsigned int value); // 发送数字量
void main()
{
init_serial(); // 初始化串口通信
init_adc(); // 初始化A/D转换
init_timer(); // 初始化定时器
while(1)
{
// 读取A/D转换的数字量
ADCIN = 1; // 选中A/D转换引脚
ad_value = ADC / 256; // A/D转换结果为10位,只取高8位
// 发送数字量到上位机
send_value(ad_value);
}
}
// 初始化串口通信
void init_serial()
{
TMOD |= 0x20; // 设置定时器1为模式2,8位自动重载
TH1 = TL1 = TIMER_VALUE; // 设置定时器初值,用于波特率发生器
TR1 = 1; // 启动定时器1
SM0 = 0; // 设置串口为模式1,8位数据位,无校验位,1位停止位
SM1 = 1;
REN = 1; // 启动串口接收
ES = 1; // 开启串口中断
EA = 1; // 开启总中断
}
// 初始化A/D转换
void init_adc()
{
ADCON = 0x00; // 设置A/D转换为模拟输入,不使用参考电压
ADCON |= 0x08; // 设置A/D转换时钟为系统时钟的1/8
}
// 初始化定时器
void init_timer()
{
TMOD &= 0xF0; // 设置定时器0为模式0,13位计数器
TH0 = TL0 = 0; // 初始化计数器
TR0 = 1; // 启动计数器
ET0 = 1; // 开启计数器中断
}
// 发送数字量
void send_value(unsigned int value)
{
SBUF = value; // 将数字量存入发送缓存器
while(!TI); // 等待发送完成
TI = 0; // 清除发送完成标志位
}
// 串口中断处理函数
void serial_interrupt() interrupt 4
{
if(RI) // 如果接收到了数据
{
RI = 0; // 清除接收中断标志位
counter_value = SBUF; // 读取计数器中断次数
}
if(TI) // 如果发送完成
{
TI = 0; // 清除发送中断标志位
}
}
// 计数器中断处理函数
void timer_interrupt() interrupt 1
{
TH0 = TL0 = 0; // 重新初始化计数器
if(COUNTER) // 如果计数器引脚为高电平
{
counter_value++; // 中断次数加1
}
if(counter_value > 0) // 如果中断次数大于0
{
counter_value--; // 中断次数减1
COUNTER = ~COUNTER; // 切换计数器引脚的电平,产生方波
}
}
```
需要注意的是,上位机和下位机之间的通信需要按照一定的协议进行,例如可以约定一个固定的命令字,上位机发送数字量时在命令字前面加上一个前缀,下位机接收到数据后根据前缀判断命令,如果是数字量则进行相应处理,如果是其他命令则忽略。具体的协议需要根据实际情况进行设计。
阅读全文