main.c
- /*****************************************************************************
- * 项 目: 基于科大讯飞XF-S4040语音播放小系统
- * 功 能: 实现SPI转UART(spi从机模式)
- * 目标系统: ATmega8L-8AU
- * 时 钟: 7.3728MHz
- * 开发软件: AVR Studio4.14
- * 版 本: Version 1.0
- * 原版时间: 2009-05-13
- * 修改时间:
- * 说 明:
- * 开发人员: zjf
- * 说 明: spi从模式MOSI刚开始设置为输入时未发生spi中断,设置为输出中断发生,有待进一步验证!
- 进一步测试,设置为输入也可以进入中断,奇怪!!!
- *****************************************************************************/
- #include<avr/io.h>
- #include <avr/wdt.h>
- #include<util/delay.h>
- #include<avr/eeprom.h>
- #include<avr/pgmspace.h>
- #include<avr/interrupt.h>
- #include<avr/signal.h>
- #include"uart.h"
- #define CHECK_4040 (PINC&0x02) //判S4040状态,1=忙,0=就绪
- #define BUSY_4040 (PORTC=PORTC|0x01) //输出S4040忙信号
- #define READY_4040 (PORTC=PORTC&0xFE) //输出S4040就绪信号
- /*----------------SPI端口定义-----------------*/
- #define SPI_CS_DDR DDRB
- #define SPI_CS_PORT PORTB
- #define SPI_CS_BIT 2
- #define SPI_SCK_DDR DDRB
- #define SPI_SCK_PORT PORTB
- #define SPI_SCK_BIT 5
- #define SPI_MOSI_DDR DDRB
- #define SPI_MOSI_PORT PORTB
- #define SPI_MOSI_BIT 3
- #define SPI_MISO_DDR DDRB
- #define SPI_MISO_PORT PORTB
- #define SPI_MISO_BIT 4
- #define SPI_PORT_INI {\
- SPI_CS_PORT |= 1<<SPI_CS_BIT;\
- SPI_SCK_PORT |= 1<<SPI_SCK_BIT;\
- SPI_MOSI_PORT |= 1<<SPI_MOSI_BIT;\
- SPI_MISO_PORT |= 1<<SPI_MISO_BIT;\
- \
- SPI_CS_DDR &= ~(1<<SPI_CS_BIT);\
- SPI_SCK_DDR &= ~(1<<SPI_SCK_BIT);\
- SPI_MOSI_DDR &= ~(1<<SPI_MOSI_BIT);\
- SPI_MISO_DDR |= 1<<SPI_MISO_BIT;\
- }
- unsigned char spi_buf[850]={0,0,0,0,0,0,0,0,0};//语音信息存储区
- volatile unsigned char spi_ok=0;
- unsigned int spi_rxd_count=0;
- unsigned int data_length=0;
- unsigned char is_head=0;
- unsigned char tmp="0";
- //格式:帧头(1字节)数据区长度(2字节)数据区(包括命令字 文本编码格式 待合成文本)
- //测试音“科大讯飞”
- //unsigned char com_buf[13]={0XFD,0X00,0X0A,0X01,0X00,0XBF,0XC6,0XB4,0XF3,0XD1,0XB6,0XB7,0XC9};
- /************************************************************
- * 函数名称:void SPI_Low()
- * 功 能:SPI初始化为低速模式
- * 入口参数:无
- * 出口参数:无
- ************************************************************/
- void SPI_Low(void)
- {
- SPCR &= ~_BV(DORD);
- SPCR = _BV(SPE)|_BV(MSTR)|_BV(SPR0);
- SPSR &= ~_BV(SPI2X);
- }
- /************************************************************
- * 函数名称:void SPI_High()
- * 功 能:SPI初始化为高速模式
- * 入口参数:无
- * 出口参数:无
- ************************************************************/
- void SPI_High(void)
- {
- //从模式下速率取决于主机
- //SPCR &= ~_BV(MSTR);//从模式,默认为从机,不用重配置
- SPCR = _BV(SPE)|_BV(SPIE);/* 使能 SPI,中断允许 */
- // SPSR |= _BV(SPI2X);
- }
- /************************************************************
- * 函数名称:void SPI_Init()
- * 功 能:SPI初始化
- * 入口参数:无
- * 出口参数:无
- ************************************************************/
- void SPI_Init(void)
- {
- SPI_High();
- SPI_PORT_INI; /* Spi Initialize */
- SPSR = 0x00;
- tmp = SPSR;
- tmp = SPDR; //清空SPI,和中断标志,使SPI空闲
- }
- /************************************************************
- * 函数名称: void port_init(void)
- * 功 能:端口初始化
- * 入口参数:无
- * 出口参数:无
- ************************************************************/
- void port_init(void)
- {
- PORTC=0xfe;//1111 1110 PC0上电输出4040为就绪状态
- DDRC=0xfd;//1111 1101 PC1检测4040状态,配置为输入; PC0输出4040状态
- PORTD = 0x00;//无上拉
- DDRD = 0x00;//输入
- }
- /************************************************************
- * 函数名称:init_devices()
- * 功 能:系统初始化
- * 入口参数:无
- * 出口参数:无
- ************************************************************/
- void init_devices(void)
- {
- //stop errant interrupts until set up
- cli(); //disable all interrupts
- port_init();
- uart_init();
- SPI_Init();
- MCUCR = 0x00;
- GICR = 0x00;
- TIMSK = 0x00; //timer interrupt sources
- sei(); //re-enable interrupts
- //all peripherals are now initialized
- }
- /************************************************************
- * 函数名称:SIGNAL(SIG_SPI)
- * 功 能:spi中断
- * 入口参数:无
- * 出口参数:无
- ************************************************************/
- SIGNAL(SIG_SPI)//spi中断
- {
- tmp="SPDR";
- if(is_head==0)
- {
- if(tmp==0xfd) //判断帧头
- is_head=1;
- }
- if(is_head==1)
- {
- spi_buf[spi_rxd_count]=tmp; //存入spi数据存储区
- spi_rxd_count++; //spi接收数据计数加1
- }
- if(spi_rxd_count==3) //如果接收到了3个字节,则计算数据长度,共两字节,高字节在前,低字节在后
- {
- data_length=spi_buf[1];
- data_length=(data_length<<8)|spi_buf[2];
- }
- if(spi_rxd_count==(data_length+3))//判断一帧数据是否结束
- {
- spi_ok=1;
- }
- }
- /************************************************************
- * 函数名称:int main()
- * 功 能:主函数
- * 入口参数:无
- * 出口参数:无
- ************************************************************/
- int main()
- {
- init_devices();
- //_delay_ms(1000); _delay_ms(1000); _delay_ms(1000);
- //send_string(com_buf , 13); //测试音“科大讯飞”
- wdt_enable(WDTO_1S); //看门狗初始化为1秒
- wdt_reset();//喂狗
- while(1)
- {
- if(spi_ok)
- {
- cli();//关中断
- BUSY_4040;//忙
- _delay_ms(10);
- wdt_reset();//喂狗
- send_string(spi_buf ,spi_rxd_count ); //向语音芯片发送信息
- wdt_reset();//喂狗
- spi_ok=0;
- spi_rxd_count=0;
- data_length=0;
- is_head=0;
- _delay_ms(10);
- sei();//开中断
- }
- if(CHECK_4040==0) //检测语音芯片状态
- {
- READY_4040; //就绪
- }
- else BUSY_4040;//忙
- wdt_reset();//喂狗
- }
- }
|