单片机DAC输出方波简易实验

在一次简单的DAC实验中,尝试通过51单片机的P0口输出方波,但发现实际输出为直线而非方波。问题源于P0口在未接上拉电阻时无法正常输出高/低电平。解决方法是在P0口外接10千欧上拉电阻,从而成功输出方波信号。P1、P2、P3口特性亦有提及。
摘要由CSDN通过智能技术生成

单片机DAC输出方波简易实验

在这里插入图片描述
在这里插入图片描述

简易的DAC实验,想要输出方波,但是输出了的是一条直线。
改P0为端口P2
在这里插入图片描述
在这里插入图片描述
排查原因了解到是端口的问题
P0口:双向8位三态I/O口,每个口可独立控制。51单片机P0口内部没有上拉电阻,为高阻状态,所以不能正常的输出高/低电平。因此,在使用P0口时务必要接上拉电阻,一般选择接入10千欧的上拉电阻。
P1口:准双向8位I/O口,每个口可独立控制,内带上拉电阻。接口输出无高阻状态,输入不能锁存,并不是真正的双向I/O口。P1口在作为输入使用前,要先向该口进行写1操作,然后单片机内部才可正确读出外部信号。
P2口:准双向8位I/O口,与P1类似
P3口:准双向8位I/O口ÿ

以下是一个简单的函数发生器的代码,它可以通过单片机DAC功能输出正弦方波和三角信号。 ```c #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #define F_CPU 16000000UL #define SAMPLE_RATE 8000 volatile uint16_t sinewave_table[256]; volatile uint16_t triangle_table[256]; volatile uint16_t square_table[256]; // 初始化三种形表 void init_tables() { for (int i = 0; i < 256; i++) { sinewave_table[i] = 2048 + (int16_t)(2047 * sin(2 * M_PI * i / 256)); triangle_table[i] = i < 128 ? i * 16 : (256 - i) * 16; square_table[i] = i < 128 ? 0 : 4095; } } // 初始化DAC void init_dac() { // 设置PB2为输出模式 DDRB |= (1 << PB2); // 设置DAC引脚PB2为输出高电平 PORTB |= (1 << PB2); // 设置DAC控制寄存器 // 使用AVcc作为参考电压 // 启用左对齐模式 // 启用DAC输出 // 启用中断 // 输出缓冲区禁用 // 设置DAC为8位分辨率 // 设置DAC时钟频率为F_CPU/2 // DAC输出电压范围为0~5V // 输出电阻为1kΩ // 启用DAC自动触发 // 设置DAC触发源为TIMER0溢出中断 // 自动触发模式为连续 // 启用DMA请求 DACB.CTRLA = DAC_CH0EN_bm | DAC_CH0TRIG_bm | DAC_CH0TRIG_bm | DAC_CH0AUTO_bm | DAC_LEFTADJ_bm; DACB.CTRLB = DAC_CHSEL_SINGLE_gc; DACB.CTRLC = DAC_REFSEL_AVCC_gc; DACB.CTRLD = DAC_CLKSEL_DIV2_gc | DAC_REFRESH_8CLK_gc; DACB.CTRLE = DAC_CONINTVAL_1CLK_gc; DACB.CTRLF = DAC_EVSEL_0_gc | DAC_EVACT_CONTINUOUS_gc | DAC_LPMODE_bm | DAC_CH0DMA_bm; } // 定时器0溢出中断服务程序 ISR(TIMER0_OVF_vect) { static uint8_t sample_counter = 0; // 从形表中获取当前样本值 uint16_t sample = 0; switch (waveform) { case SINE_WAVE: sample = sinewave_table[sample_counter]; break; case TRIANGLE_WAVE: sample = triangle_table[sample_counter]; break; case SQUARE_WAVE: sample = square_table[sample_counter]; break; } // 设置DAC输出值 DACB.CH0DATA = sample; // 更新计数器 sample_counter++; if (sample_counter >= 256) sample_counter = 0; } int main() { // 初始化形表 init_tables(); // 初始化定时器0 TCCR0A = 0; TCCR0B = (1 << CS00); // 设置分频系数为1,时钟频率为F_CPU TIMSK0 = (1 << TOIE0); // 开启定时器0溢出中断 // 初始化DAC init_dac(); // 启用全局中断 sei(); // 设置初始形为正弦 waveform = SINE_WAVE; while (1) { // 切换形 if (/* 判断是否需要切换形 */) waveform = /* 切换到下一个形 */; _delay_ms(500); } return 0; } ``` 以上代码中,我们使用了AVR单片机DAC功能,可以输出0~5V的模拟信号。我们使用了定时器0的溢出中断来触发DAC输出,每次中断时从预先生成好的形表中获取当前样本值,然后将其写入DAC缓冲区中。同时,我们还使用了一个while循环来控制形的切换,可以根据需要修改判断条件和切换逻辑。在实际使用时,我们可以将单片机DAC引脚连接到外部电路中,以输出各种复杂的模拟信号。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值