我想做一个wav。使用 STM32微控制器的播放器。我的第一步是使用 STM32F103C8T6、SPI 接口和外部 DAC MCP4921 生成正弦波。但是,它不起作用。
我附上我的设备的原理图。
我在 STM32CubeIDE 中使用 CMSIS 编写了我的程序的 2 个版本。在程序的第一个版本中,定时器每秒产生一个中断。每 4 秒微控制器使用 SPI 接口向外部 DAC 发送一个数字值。我用万用表检查了 DAC 的输出,电压水平是正确的。这是工作。我还检查了微控制器的 RCC、GPIO、SPI 和定时器块:它们都可以工作。因此,该程序的第一个版本运行完美。
在程序的第二个版本中,缓冲区初始化为 100 个正弦波值。一个定时器产生一个频率为 40kHz 的中断,微控制器使用 SPI 接口向外部 DAC 发送一个正弦值。正弦波的频率应为 400Hz。但是,当我插入耳机时,我听不到正确的声音。当我通过计算机的麦克风输入将信号插入虚拟示波器时,我也看不到任何东西(不幸的是我没有示波器)。当我改变采样频率(定时器的中断频率)时,我要么听不到任何声音,要么听到一些令人不安的胡言乱语。
感谢你的帮助。
- //#include "main.h"
- #include "stm32f1xx.h"
- void RCCinit(void);
- void GPIOinit(void);
- void SPIinit(void);
- void SPItransmit(unsigned int data);
- void tiMinit(void);
- unsigned int i=0;
- unsigned int buf[100]=
- {
- 620,659,698,736,774,812,848,884,919,952,
- 984,1015,1044,1072,1098,1122,1143,1163,1181,1196,
- 1210,1221,1229,1235,1239,1240,1239,1235,1229,1221,
- 1210,1196,1181,1163,1143,1122,1098,1072,1044,1015,
- 984,952,919,884,848,812,774,736,698,659,
- 620,581,542,504,466,428,392,356,321,288,
- 256,225,196,168,142,118,97,77,59,44,
- 30,19,11,5,1,0,1,5,11,19,
- 30,44,59,77,97,118,142,168,196,225,
- 256,288,321,356,392,428,466,504,542,581
- };
- int main (void)
- {
- RCCinit();
- GPIOinit();
- SPIinit();
- TIMinit();
- while(1)
- {
- }
- }
- void RCCinit(void)
- {
- FLASH->ACR|=FLASH_ACR_PRFTBE; //Prefetch is enabled.
- while(!(FLASH->ACR&FLASH_ACR_PRFTBS)); //Prefetch buffer is disabled.
- FLASH->ACR&=~FLASH_ACR_HLFCYA; //Half cycle is disabled.
- FLASH->ACR&=~FLASH_ACR_LATENCY;
- //FLASH->ACR|=FLASH_ACR_LATENCY_0; //One wait state, if 24 MHz < SYSCLK ≤ 48 MHz
- FLASH->ACR|=FLASH_ACR_LATENCY_1; //Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz.
- RCC->CR|=RCC_CR_HSEON; //HSE oscillator ON. 8MHz.
- while(!(RCC->CR&RCC_CR_HSERDY)); //HSE oscillator not ready.
- RCC->CFGR&=~RCC_CFGR_PLLXTPRE; //HSE clock not divided. 8MHz.
- RCC->CFGR|=RCC_CFGR_PLLSRC; //HSE oscillator clock selected as PLL input clock.
- RCC->CFGR&=~RCC_CFGR_PLLMULL;
- RCC->CFGR|=RCC_CFGR_PLLMULL9; //PLL input clock x 9. 72MHz.
- RCC->CFGR&=~RCC_CFGR_HPRE; //SYSCLK not divided.
- RCC->CFGR&=~RCC_CFGR_PPRE1;
- RCC->CFGR|=RCC_CFGR_PPRE1_DIV2; //HCLK divided by 2. 36MHz.
- RCC->CFGR&=~RCC_CFGR_PPRE2; //HCLK not divided.
- RCC->CFGR&=~RCC_CFGR_USBPRE; //PLL clock is divided by 1.5. 48MHz.
- RCC->CR|=RCC_CR_PLLON; //PLL ON.
- while(!(RCC->CR&RCC_CR_PLLRDY)); //PLL unlocked.
- RCC->CFGR&=~RCC_CFGR_SW;
- RCC->CFGR|=RCC_CFGR_SW_PLL; //PLL selected as system clock.
- while(!(RCC->CFGR&RCC_CFGR_SWS_PLL)); //PLL used as system clock.
- RCC->APB1ENR|=RCC_APB1ENR_TIM2EN; //TIM2 timer clock enable.
- RCC->APB2ENR|=RCC_APB2ENR_IOPCEN|RCC_APB2ENR_IOPAEN|RCC_APB2ENR_AFIOEN|RCC_APB2ENR_SPI1EN; //IO port C, IO port A, Alternate function I/O, SPI 1 clock enabled.
- }
- void GPIOinit(void)
- {
- //SPI pins.
- GPIOA->CRL|=GPIO_CRL_MODE4|GPIO_CRL_MODE5|GPIO_CRL_MODE7; //Output mode, max speed 50 MHz.
- GPIOA->CRL&=~(GPIO_CRL_CNF4|GPIO_CRL_CNF5|GPIO_CRL_CNF7);
- GPIOA->CRL|=GPIO_CRL_CNF4_1|GPIO_CRL_CNF5_1|GPIO_CRL_CNF7_1; //Alternate function output Push-pull.
- //C13
- GPIOC->CRH|=GPIO_CRH_MODE13; //Output mode, max speed 50 MHz.
- GPIOC->CRH&=~GPIO_CRH_CNF13; //General purpose output push-pull.
- GPIOC->ODR|=GPIO_ODR_ODR13;
- }
- void SPIinit(void)
- {
- SPI1->CR1&=~SPI_CR1_BR;
- SPI1->CR1|=SPI_CR1_BR_0; //fPCLK/4=72MHz/4=18MHz.
- SPI1->CR1&=~(SPI_CR1_CPOL|SPI_CR1_CPHA); //CK to 0 when idle. The first clock transition is the first data capture edge.
- SPI1->CR1|=SPI_CR1_DFF; //16-bit data frame format is selected for transmission/reception.
- SPI1->CR1&=~SPI_CR1_LSBFIRST; //MSB transmitted first.
- SPI1->CR1&=~(SPI_CR1_SSM|SPI_CR1_SSI); //Software slave management disabled.
- SPI1->CR2|=SPI_CR2_SSOE; //SS output is enabled in master mode and when the cell is enabled. The cell cannot work in a multimaster environment.
- SPI1->CR1&=~(SPI_CR1_BIDIMODE|SPI_CR1_RXONLY); //2-line unidirectional data mode selected. Full duplex (Transmit and receive).
- SPI1->CR1&=~SPI_CR1_CRCEN; //CRC calculation disabled.
- SPI1->CR2&=~(SPI_CR2_TXEIE|SPI_CR2_RXNEIE|SPI_CR2_ERRIE|SPI_CR2_TXDMAEN|SPI_CR2_RXDMAEN); //TXE, RXNE, Error interrupt is masked. Tx, Rx buffer DMA disabled.
- SPI1->I2SCFGR&=~SPI_I2SCFGR_I2SMOD; //SPI mode is selected.
- SPI1->CR1|=SPI_CR1_MSTR; //Master configuration.
- }
- void SPItransmit(unsigned int data)
- {
- SPI1->CR1|=SPI_CR1_SPE; //Peripheral enabled.
- while(!(SPI1->SR&SPI_SR_TXE)); //Tx buffer not empty.
- SPI1->DR=0x7000U|(data&0xFFFU);
- while(!(SPI1->SR&SPI_SR_TXE)); //Tx buffer not empty.
- while(SPI1->SR&SPI_SR_BSY); //SPI (or I2S) is busy in communication or Tx buffer is not empty.
- SPI1->CR1&=~SPI_CR1_SPE; //Peripheral disabled.
- }
- void TIMinit(void)
- {
- //fapb1=36MHz. fclk=36*2=72MHz.
- TIM2->CR1&=~TIM_CR1_UDIS; //UEV enabled.
- TIM2->CR1&=~TIM_CR1_URS; //Any of the following events generate an update interrupt or DMA request if enabled. These events can be: – Counter overflow/underflow. – Setting the UG bit. – Update generation through the slave mode controller.
- TIM2->CR1&=~TIM_CR1_OPM; //Counter is not stopped at update event.
- TIM2->CR1&=~TIM_CR1_DIR; //Counter used as upcounter.
- TIM2->CR1&=~TIM_CR1_CMS; //Edge-aligned mode.
- TIM2->CR1|=TIM_CR1_ARPE; //TIMx_ARR register is buffered.
- TIM2->CR1&=~TIM_CR1_CKD; //tDTS = tCK_INT.
- TIM2->DIER|=TIM_DIER_UIE; //Update interrupt enabled.
- NVIC_EnableIRQ(TIM2_IRQn);
- TIM2->PSC=17; //Prescaler value.
- TIM2->ARR=99; //Auto-reload register. fUEV=72MHz/()=Hz.
- TIM2->CNT=0; //Counter value.
- TIM2->CR1|=TIM_CR1_CEN; //Counter enabled.
- }
- void TIM2_IRQHandler(void)
- {
- //C13 мигает
- //GPIOC->ODR^=GPIO_ODR_ODR13;
- if(i==100)
- {
- i=0;
- }
- SPItransmit(buf);
- i++;
- TIM2->SR&=~TIM_SR_UIF; //Update interrupt flag. It is cleared by software. No update occurred.
- }
0
|
1个回答
|
|
|