打印
[AVR单片机]

pwm的设置

[复制链接]
1181|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
沙发
huangxz| | 2014-3-20 14:51 | 只看该作者
16e6/20e3 = 800.0

ocr1a设置成800比就有这个频率输出了么

使用特权

评论回复
板凳
pengzhou91|  楼主 | 2014-3-20 15:42 | 只看该作者
huangxz 发表于 2014-3-20 14:51
16e6/20e3 = 800.0

ocr1a设置成800比就有这个频率输出了么

但是那个占空比就不能随音频信号变化了

使用特权

评论回复
地板
huangxz| | 2014-3-20 16:00 | 只看该作者
周期可以有OCRnA指定,占空比可以有OCRnx指定

使用特权

评论回复
5
pengzhou91|  楼主 | 2014-3-20 16:49 | 只看该作者
huangxz 发表于 2014-3-20 16:00
周期可以有OCRnA指定,占空比可以有OCRnx指定

好的谢谢了

使用特权

评论回复
6
pengzhou91|  楼主 | 2014-3-20 19:11 | 只看该作者
huangxz 发表于 2014-3-20 16:00
周期可以有OCRnA指定,占空比可以有OCRnx指定

还想问一下,我的ADC工作在自动触发状态,T/C0比较匹配触发源,在配置T/C0初始化时需要设置成中断允许吗

使用特权

评论回复
7
huangxz| | 2014-3-20 22:38 | 只看该作者
pengzhou91 发表于 2014-3-20 19:11
还想问一下,我的ADC工作在自动触发状态,T/C0比较匹配触发源,在配置T/C0初始化时需要设置成中断允许吗 ...

不需要设置源的中断,匹配自动触发ADC开始转换。

使用特权

评论回复
评分
参与人数 1威望 +6 收起 理由
qin552011373 + 6 很给力!
8
pengzhou91|  楼主 | 2014-4-6 12:09 | 只看该作者
huangxz 发表于 2014-3-20 22:38
不需要设置源的中断,匹配自动触发ADC开始转换。

现在把东西做出来了,但输出端还有很大的噪声是为什么啊

使用特权

评论回复
9
huangxz| | 2014-4-6 15:23 | 只看该作者
pengzhou91 发表于 2014-4-6 12:09
现在把东西做出来了,但输出端还有很大的噪声是为什么啊

滤波不合适,你建个matlab模型,仿真一下就知道了

使用特权

评论回复
10
pengzhou91|  楼主 | 2014-4-6 16:54 | 只看该作者
本帖最后由 pengzhou91 于 2014-4-6 17:01 编辑
huangxz 发表于 2014-4-6 15:23
滤波不合适,你建个matlab模型,仿真一下就知道了

#include<iom16v.h>  //包含DDR等寄存器
#include<macros.h>  //AVR单片机中特有的位指令(BIT)
#include"nRF2401.h"

#pragma interrupt_handler ext_int0_isr:2                //外部中断0
#pragma interrupt_handler ext_int1_isr:3                //外部中断1
#pragma interrupt_handler adc_isr:15                // AD转换结束中断

extern uchar RX_BUF[RX_PLOAD_WIDTH]={0};

unsigned char play_on=0;
uchar byte_count=0;

unsigned char adc_data_H = 0;        //ADC采样值
unsigned char SPEED = 0x31;

void interrupt_init(void);
void ext_int0_isr(void);
void ext_int1_isr(void);


void timer0_init(void)        //定时器0初始化函数
{
        TCCR0 = 0X0A;  //CTC模式,8分频,(8MHZ/8=1000kH)的时钟信号
        TCNT0 = 0X00;  //计数值寄存器,相当于设置计数初值
        OCR0 = SPEED;
//        OCR0 = 0X31;
//        OCR0 = 0X31;  //输出比较寄存器,CTC模式下计数上限值,比较匹配中断使能初值
                                //(49+1)/1000KHZ=0.05ms
}

void timer1_init(void)  //定时计数器1的初始化
{
        DDRD |= BIT(4) | BIT(5);     //PD5脚为输出脚
        PORTD &= BIT(4) | BIT(5); //M16的OC1A为输出0电平
        TCCR1A=0x00;
        TCCR1B=0x00;
        TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<WGM10);        //比较匹配时清0,8位快速PWM;T/C1控制寄存器A
        TCCR1B |= (1<<WGM12) | (1<<CS10);  //无预分频,T/C1控制寄存器B
        
//        OCR1A = 0x007F;  //16位寄存器,输出比较寄存器1A-OCR1A
}

void adc_init(void)                //---->ADC初始化
{
        DDRA &= ~BIT(0);                //输入方式
        PORTA &= ~BIT(0);        //不带上拉
        ADMUX = 0X60;        //AVCC  ADC结果左对齐,选择通道ADC0
        SFIOR &= 0x1F;
        SFIOR |= 0x60;        //选择T/C0比较匹配中断为ADC触发源
        ADCSRA = 0XAB; //ADC使能,ADC自动转换触发8分频,允许ADC中断
}

//adc中断程序,最高采样率;为了保持与发射端相同频率,在此处理数据;
void adc_isr(void)        //ADC中断函数
{
        adc_data_H = ADCH;
        if(play_on)
        {
                DDRD |= (1<<PD4);
                OCR1A = RX_BUF[byte_count];
                //PORTC = RX_BUF[byte_count];
                RX_BUF[byte_count]=0;
                byte_count++;
                if (byte_count == 32)
                {
                        byte_count = 0;
                        play_on = 0;
                }
        }
        else//没有收到数据则关闭pwm
        {
                DDRD &= ~(1<<PD4);//没有数据时设置为输入,防止产生高频噪声;
        }
        OCR1B = adc_data_H;
        TIFR = TIFR;//清除T/C0中断标志
        ADCSRA |= (1<<ADIF);//清除ADC中断
}

int main(void)
{
        DDRC = 0xFF;
        PORTC = 0xFF;
        
        init_NRF24L01();
        SetRX_Mode();//设置为接收模式
        
        interrupt_init();//外部中断

        timer0_init();
        timer1_init();
        adc_init();

        SREG |= BIT(7);        //使能全局中断
        
        
        while(1)
        {
                sta = SPI_Read(STATUS);      // 读取状态寄存其来判断数据接收状况;
                if(RX_DR)                 // 判断是否接收到数据RX_DR==1?
                {
                        Low_24L01_CE;    //SPI使能
                        SPI_Read_Buf(RD_RX_PLOAD,RX_BUF,TX_PLOAD_WIDTH);// 读取接收数据;
                        SPI_RW_Reg(WRITE_REG + STATUS, sta);    //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
                        play_on = 1;
                }
                Hign_24L01_CE;//接收模式
        }
        return 0;
}



void interrupt_init(void)//中断初始化
{
        MCUCR |= (1<<ISC11) | (1<<ISC01);//设置为下降沿触发
        GICR |= (1<<INT0) | (1<<INT1);//使能外部中断
}

void ext_int0_isr(void)
{
        SPEED++;
        OCR0 = SPEED;
        GIFR |= (1<<INTF0);
}

void ext_int1_isr(void)
{
        SPEED--;
        OCR0 = SPEED;
        GIFR |= (1<<INTF1);
}

这是我主函数的程序,从PD5输出PWM波,还原声音,但是为什么还要设置PD4呢

使用特权

评论回复
11
pengzhou91|  楼主 | 2014-4-6 17:03 | 只看该作者
现在在学校学习好迷茫啊,感觉好多东西要学,又不知道该如何下手

使用特权

评论回复
12
huangxz| | 2014-4-6 17:32 | 只看该作者
pengzhou91 发表于 2014-4-6 16:54
#include  //包含DDR等寄存器
#include  //AVR单片机中特有的位指令(BIT)
#include"nRF2401.h"

PD4,PD5都可以输出PWM,任意选一个就可以

使用特权

评论回复
13
pengzhou91|  楼主 | 2014-4-6 18:45 | 只看该作者
huangxz 发表于 2014-4-6 17:32
PD4,PD5都可以输出PWM,任意选一个就可以

那为什么pwm输出的波形和采样信号不一样呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

33

帖子

1

粉丝