请教马老师,2个中断存在依赖性,如何较好的控制?
马老师,您好。在双机通讯中,由A向B持续不断发送数据(这些数据是正弦波形函数的列表值),B接受后,存储在一个FIFO中,另外一个中断函数T/C0_overflow中,取这个FIFO存储器的值(也就是正弦波形函数的列表值)来改变OCR0B,生成PWM,经过滤波后,从而达到在B方输出正弦波的目的。
我的困难是:我用Usart_Rx中断来接受数据,用Timer0_ovf中断来修改OCR0B,如何控制这两个中断?
我希望这两个中断互不干扰,各做各的。但是从实现角度来看,互不干扰是不可能的,使能了溢出中断就一定会影响到数据接收的中断;而且溢出中断程序中所需要的OCR0B的数值是由接受数据中断的程序提供的。
后来我想我用polling来代替中断的方法接收数据,这样就不存在矛盾了,但是程序运行有问题,溢出中断中读取OCR0B的值不能按我想的那样,输出的正弦波不够平滑,并且频率是以前的十分之一。
不知道您可以给我提供一些建议吗?
谢谢。 我已经不太明白你到底想做什么。
关于AVR本身功能模块的应用我可以给你些建议,至于产品的功能的具体实现,已经超出了本讨论组的范围。
如同你买了一台PC,PC本身没有问题,你在上面自己编写的程序有问题的话,微软公司也不知道如何帮你解决。 也许是我的表达能力有问题吧,请见谅。
通过示波器观测发现问题出在接受数据的速度太慢,而溢出中断更新OCR0B的值太快,于是通过调整波特率就可以解决了。
但是我是用查询的方法来接受数据,如果改用中断,还是有问题。
附加代码如下:
//reception
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "son.h"
#include "fifo.h"
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
//RTS CTS 流量控制
#define RTS_inactive PORTD &= ~(1<<PD3) //level low
#define RTS_active PORTD |=(1<<PD3)//level high
#define CTS_inactive !(PIND &(1<<2)) //level low
#define CTS_active PIND &(1<<2)//level high
/* declaration of variables */
volatile uint8_t counter_repetition;
uint8_t testFifo_buf; // FIFO的大小是64bytes
fifo_t testFifo = {testFifo_buf, sizeof testFifo_buf-1, 0, 0}, *myFifo= &testFifo; /* create a testFifo and a pointer to it */
volatile uint8_t i_push;
uint8_t buff;
/* functions */
// Init Usart
void Init_Usart(unsigned int baudrate)
{
UBRR0H = (unsigned char)(baudrate>>8);
UBRR0L = (unsigned char)baudrate;
UCSR0B = 0x00; //disable while setting baud rate
UCSR0A = (1<<U2X0);
// Enable receiver
//UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
// Async mode, 8bits data, 1bits stop
UCSR0C = (1<<UCSZ00)|(1<<UCSZ01) ;
}
// Init Port
void Init_Port_Son(void)
{
// Port D init
//PORTD.0 -> IN RxD
//PORTD.1 -> OUT TxD
//PORTD.2 -> IN CTS
//PORTD.3 -> OUT RTShigh level means enable RTS
//PORTD.5 -> OUT PWM audio output from timer compare
PORTD = 0b11010011;
DDRD= 0b11101010;
}
// Timer0 Init
void Init_Timer0_Son(void)
{
//Fast PWM mode, TOP=0xFF,
TCCR0A=(1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
//CLKI/O8MHz
TCCR0B=(1<<CS00);
//enable TOIE0
//TIMSK0=(1<<TOIE0);
}
// Init Total
void Init_Total_Son(void)
{
CLKPR = (1<<CLKPCE); // set Clock Prescaler Change Enable
Init_Port_Son();
//Init_Usart(103); //9600bits/s baudrate for 8MHz, 太慢
Init_Usart(1); //0.5Mbits/s baudrate for 8Mhz
Init_Timer0_Son();
}
// recept funtion
char Usart_Rx(void)
{
while (!(UCSR0A & (1<<RXC0)));
return UDR0;
}
/* interruption */
// Timer0 overflow
ISR(TIMER0_OVF_vect)
{
counter_repetition++;
if(counter_repetition == 4) //重复四次,Fpwm=31KHz
{
OCR0B = pullFifo(myFifo);//取FIFO的值到OCR0B
counter_repetition =0;
}
}
// interruption of reception
/* 这种方法不可以
ISR(USART_RX_vect)
{
//if(!(isFifoFull(myFifo)))
// pushFifo(myFifo,UDR0);
//TIMSK0 = (1<<TOIE0);
if(!(isFifoFull(myFifo)))
{
RTS_active; //il faut remettre cette condition
pushFifo(myFifo,UDR0);
TIMSK0 = (1<<TOIE0); // just useful for the first time
}
else
RTS_inactive;
}
*/
/* Programme Main */
int main(void)
{
counter_repetition = 0;
Init_Total_Son();
resetFifo(myFifo);
sei();
while(CTS_inactive);
RTS_active;
while(1)
{
if(!(isFifoFull(myFifo))) //如果FIFO没满
{
RTS_active;
pushFifo(myFifo,Usart_Rx());//存入数据到FIFO
TIMSK0 = (1<<TOIE0); // just useful for the first time
}
else
RTS_inactive;
}
return 0;
}
FIFO的程序不是我写的,不能公布,不好意思。
//Butterfly : 发送方
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "Butterfly_sendson.h"
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
//RTS CTS
#define RTS_inactive PORTB &= ~(1<<PB7) //level low
#define RTS_active PORTB |=(1<<PB7)//level high
#define CTS_inactive !(PINB &(1<<6)) //level low
#define CTS_active PINB &(1<<6)//level high
/* declaration of variables */
/************************** Sin Table **********************
* Samples table : one period sampled on 128 samples and *
* quantized on 7 bit *
* formule: f(x) = 64 + 63 * sin(2πx/128) x∈ *
***********************************************************/
const uint8_t table1_SinParam PROGMEM = {
64, 67, 70, 73, 76, 79, 82, 85,
88, 91, 94, 96, 99, 102,104,106,
109,111,113,115,116,118,120,121,
122,123,124,125,126,126,127,127,
127,127,127,126,126,125,124,123,
122,121,120,118,116,115,113,111,
109,106,104,102,99, 96, 94, 91,
88, 85, 82, 79, 76, 73, 70, 67,
64, 61, 58, 55, 52, 49, 46, 43,
40, 37, 34, 32, 29, 26, 24, 22,
19, 17, 15, 13, 12, 10, 8,7,
6,5,4,3,2,2,1,1,
1,1,1,2,2,3,4,5,
6,7,8,10, 12, 13, 15, 17,
19, 22, 24, 26, 29, 32, 34, 37,
40, 43, 46, 49, 52, 55, 58, 61};
volatile uint8_t counter_interrupt;
volatile uint8_t send_son_active;
/* init */
// init usart
void Init_Usart_Butterfly(uint16_t baudrate)
{
UBRRH = (unsigned char)(baudrate>>8);
UBRRL = (unsigned char)baudrate;
UCSRB = 0x00; //disable while setting baud rate
// double vitesse
UCSRA = (1<<U2X);
// Enabletransmitter and receiver
UCSRB = (1<<TXEN)|(1<<RXEN);
// Async mode, 8bits data, 1bits stop
UCSRC = (1<<UCSZ0)|(1<<UCSZ1) ;
}
// Init Port
void Init_Port_Butterfly(void)
{
// PE0RXDIN
// PE1TXDOUT
// PE2XCK/AIN0IN
// PE3AIN1IN
// PE4SCL/USCK BI
// PE5SDA/DIBI
// PE6DOBI
// PE7RST_FLASH OUT
PORTE = 0b11111111;
DDRE= 0b10000010;
// PB0/SS OUT desactiver
// PB1SCK OUT
// PB2MISOIN
// PB3MOSIOUT
// PB4OC0
// PB5OC1A
// PB6OC1BCTS IN read RTS of TUX
// PB7OC2 RTS OUT
PORTB = 0b00100000;
DDRB= 0b10010000;
}
// init total
void Init_Total_Butterfly(void)
{
CLKPR = (1<<CLKPCE); // set Clock Prescaler Change Enable
Init_Port_Butterfly();
//Init_Usart_Butterfly(103); //9600bits/s baudrate for 8Mhz
Init_Usart_Butterfly(1); //250Kbits/s baudrate for 8Mhz
EIMSK = (1<<PCIE1); //Pin change interrupt enable
PCMSK1 = (1<<PCINT14); //Pin change enable PB6_CTS
}
/* send a character function*/
void Put_Char(char c)
{
while (!(UCSRA & (1<<UDRE)));
UDR = c;
}
/* interrupt */
ISR(PCINT1_vect)
{
switch (counter_interrupt % 2)
{
case 0:
{
counter_interrupt++;
send_son_active=1;
} break;
case 1:
{
counter_interrupt++;
send_son_active=0;
} break;
}
}
/* programme main */
int main (void)
{
uint8_t data = 0;
uint8_t step_width = 8;
uint8_t position_in_table = 0;
uint8_t Num_Sample;
Num_Sample = 128/step_width;
send_son_active = 0;
counter_interrupt = 0;
Init_Total_Butterfly();
sei();
RTS_active;
while(1)
{
while(Num_Sample>0)
{
if(send_son_active)
{
Num_Sample--;
position_in_table += step_width;
if (position_in_table > 127) position_in_table -= 128;
data = pgm_read_byte(&table1_SinParam);
Put_Char(data);
if(Num_Sample == 0)
Num_Sample = 128/step_width;
}
}
}
return 0;
}
-----此内容被Lily1979于2007-03-22,01:25:37编辑过 使用两个变量 data_pre,data_new.
Usart_Rx中断接受到的数据,放在data_new中。
每次Timer0_ovf中断,进入中断后,判断data_pre,data_new值是否相同。不同修改OCR0B;并将data_pre = data_new。相同不修改OCR0B。
页:
[1]