⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sample.c

📁 AVR单片机实现AD采集PWM播放声音功能
💻 C
字号:
#include “io8535.h”
#include <ina90.h>
#include “stdlib.h”
#include “dataflash.h”
// prototypes
void setup (void);
void erasing (void);
void recording (void);
void interrupt[ADC_vect] sample_ready (void);
void write_to_flash (unsigned char ad_data);
void playback (void);
void next_page_to_next_buffer (unsigned char active_buffer, unsigned int page_counter);
void interrupt[TIMER1_OVF1_vect] out_now(void);
void active_buffer_to_speaker (unsigned char active_buffer);
// global variables
volatile unsigned char wait = 0;
void setup(void)
{
	DDRB = 0xBD; // SPI Port initialisation
	// SCK, MISO, MOSI, CS, LED, WP , RDYBSY, RST
	// PB7, PB6, PB5, PB4, PB3, PB2 , PB1, PB0
	// O I O O O O I O
	// 1 0 1 1 1 1 0 1
	PORTB = 0xFF; // all outputs high, inputs have pullups (LED is off)
	DDRA = 0x00; // define port A as an input
	PORTA = 0x00;
	DDRD = 0x10; // define port D as an input (D4: output)
	_SEI(); // enable interrupts
}
void erasing(void)
{
	unsigned int block_counter = 0;
	unsigned char temp = 0x80;
	ACSR |= 0x02; // set signal flag that new data has to be recorded next
	// interrupt disabled, SPI port enabled, master mode, MSB first,
	// SPI mode 3, Fcl/4
	SPCR = 0x5C;
	while (block_counter < 512)
	{
		PORTB &= ~DF_CHIP_SELECT; // enable DataFlash
		SPDR = BLOCK_ERASE;
		while (!(SPSR & temp)); // wait for data transfer to be completed
			SPDR = (char)(block_counter>>3);
		while (!(SPSR & temp)); // wait for data transfer to be completed
			SPDR = (char)(block_counter<<5);
		while (!(SPSR & temp)); // wait for data transfer to be completed
			SPDR = 0x00; // don’t cares
		while (!(SPSR & temp)); // wait for data transfer to be completed
			PORTB |= DF_CHIP_SELECT; // disable DataFlash
		block_counter++;
		while(!(PINB & 0x02)); // wait until block is erased
	}
	SPCR = 0x00; //disable SPI
}
void recording(void)
{
	// interrupt disabled, SPI port enabled, master mode, MSB first,
	// SPI mode 3, Fcl/4
	SPCR = 0x5C;
	ADMUX = 0x00; // A/D converter input pin number = 0
	ADCSR = 0xDD; // single A/D conversion, fCK/32,
	// conversion now started
	while (!(PIND & 8)); // loop while button for recording (button
	// 3) is pressed
	ADCSR = 0x00; // disable AD converter
	SPCR = 0x00; // disable SPI
}
void interrupt[ADC_vect] sample_ready(void)
{
	unsigned char count = 0;
	while (count < 6) count++; // wait some cycles
	ADCSR |= 0x40; // start new A/D conversion
	write_to_flash(ADC-0x1D5); // read data, convert to 8 bit
	// and store in flash
}
void write_to_flash(unsigned char flash_data)
{
	static unsigned int buffer_counter;
	static unsigned int page_counter;
	unsigned char temp = 0x80;
	if((ACSR & 0x02)) // if flag is set that new data has
	// to be written
	{
		buffer_counter = 0;
		page_counter = 0; // reset the counter if new data
		// has to be written
		ACSR &= 0xFD; // clear the signal flag
	}
	while(!(PINB & 0x02)); // check if flash is busy
		PORTB &= ~DF_CHIP_SELECT; // enable DataFlash
		SPDR = BUFFER_1_WRITE;
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = 0x00; // don’t cares
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = (char)(buffer_counter>>8);// don’t cares plus first two bits
		// of buffer address
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = (char)buffer_counter; // buffer address (max. 2^8 = 256 pages)
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = flash_data; // write data into SPI Data Register
	while (!(SPSR & temp)); // wait for data transfer to be completed
		PORTB |= DF_CHIP_SELECT; // disable DataFlash
		buffer_counter++;
	if (buffer_counter > 528) // if buffer full write buffer into
	// memory page
	{
		buffer_counter = 0;
		if (page_counter < 4096) // if memory is not full
		{
			PORTB &= ~DF_CHIP_SELECT;// enable DataFlash
			SPDR = B1_TO_MM_PAGE_PROG_WITHOUT_ERASE;// write data from
			//buffer1 to page
			while (!(SPSR & temp)); // wait for data transfer to be completed
				SPDR = (char)(page_counter>>6);
			while (!(SPSR & temp));// wait for data transfer to be completed
				SPDR = (char)(page_counter<<2);
			while (!(SPSR & temp)); // wait for data transfer to be completed
				SPDR = 0x00; // don’t cares
			while (!(SPSR & temp)); // wait for data transfer to be completed
				PORTB |= DF_CHIP_SELECT;// disable DataFlash
				page_counter++;
		}
		else
		{
			PORTB |= 0x08; // turn LED off
			while (!(PIND & 8)); // wait until button for recording
			// (button 3) is released
		}
	}
}
void playback(void)
{
	unsigned int page_counter = 0;
	unsigned int buffer_counter = 0;
	unsigned char active_buffer = 1;// active buffer = buffer1
	unsigned char temp = 0x80;
	TCCR1A = 0x21; // 8 bit PWM, using COM1B
	TCNT1 = 0x00; // set counter1 to zero
	TIFR = 0x04; // clear counter1 overflow flag
	TIMSK = 0x04; // enable counter1 overflow interrupt
	TCCR1B = 0x01; // counter1 clock prescale = 1
	OCR1B = 0x00; // set output compare register B to zero
	// interrupt disabled, SPI port enabled, master mode, MSB first,
	// SPI mode 3, Fcl/4
	SPCR = 0x5C;
	// read page0 to buffer1
	next_page_to_next_buffer (active_buffer, page_counter);
	while (!(PINB & 0x02)); // wait until page0 to buffer1
	// transaction is finished
	while ((page_counter < 4095)&(!(PIND & 2)))// while button for playback
	// (button 1) is pressed
	{
		page_counter++; // now take next page
		next_page_to_next_buffer (active_buffer, page_counter);
		active_buffer_to_speaker (active_buffer);
		if (active_buffer == 1) // if buffer1 is the active buffer
		{
			active_buffer++; // set buffer2 as active buffer
		}
		else // else
		{
			active_buffer--; // set buffer1 as active buffer
		}
	}
	TIMSK = 0x00; // disable all interrupts
	TCCR1B = 0x00; // stop counter1
	SPCR = 0x00; // disable SPI
}
void next_page_to_next_buffer (unsigned char active_buffer, unsigned int page_counter)
{
	unsigned char temp = 0x80;
	while(!(PINB & 0x02)); // wait until flash is not busy
	PORTB &= ~DF_CHIP_SELECT; // enable DataFlash
	if (active_buffer == 1) // if buffer1 is the active buffer
	{
		SPDR = MM_PAGE_TO_B2_XFER; // transfer next page to buffer2
	}
	else // else
	{
		SPDR = MM_PAGE_TO_B1_XFER; // transfer next page to buffer1
	}
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = (char)(page_counter >> 6);
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = (char)(page_counter << 2);
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = 0x00; // write don’t care byte
	while (!(SPSR & temp)); // wait for data transfer to be completed
	PORTB |= DF_CHIP_SELECT; // disable DataFlash and start transaction
}

void interrupt[TIMER1_OVF1_vect] out_now(void)
{
	wait = 0; // an interrupt has occured
}

void active_buffer_to_speaker (unsigned char active_buffer)
{
	// until active buffer not empty read active buffer to speaker
	unsigned int buffer_counter = 0;
	unsigned char temp = 0x80;
	PORTB &= ~DF_CHIP_SELECT; // enable DataFlash
	if (active_buffer == 1) // if buffer1 is the active buffer
	{
		SPDR = BUFFER_1_READ; // read from buffer1
	}
	else // else
	{
		SPDR = BUFFER_2_READ; // read from buffer2
	}
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = 0x00; // write don’t care byte
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = 0x00; // write don’t care byte
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = 0x00; // start at buffer address 0
	while (!(SPSR & temp)); // wait for data transfer to be completed
		SPDR = 0x00; // write don’t care byte
	while (!(SPSR & temp)); // wait for data transfer to be completed
	while (buffer_counter < 528)
	{
		SPDR = 0xFF; // write dummy value to start register shift
		while (!(SPSR & temp)); // wait for data transfer to be completed
		while(wait); // wait for timer1 overflow interrupt
		OCR1B = SPDR; // play data from shift register
		wait = 1; // clear the signal flag
		buffer_counter++;
	}
	PORTB |= DF_CHIP_SELECT; // disable DataFlash
}
void main(void)
{
	setup();
	for(;;)
	{
		if (!(PIND & 8)) // if button for recording (button 3)
		// is pressed
		{
			PORTB &= 0xF7; // turn LED on
			recording();
		}
		if (!(PIND & 4)) // if button for erasing (button 2)
		// is pressed
		{
			PORTB &= 0xF7; // turn LED on
			erasing();
			while (!(PIND & 4));// wait until button for erasing (button 2)
			// is released
		}
		if (!(PIND & 2)) // if button for playback (button 1)
		// is pressed
		{
			PORTB &= 0xF7; // turn LED on
			playback();
			while (!(PIND & 2));// wait until button for playback (button 1)
			// is released
		}
		PORTB |= 0x08; // turn LED off while running idle
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -