Hallo an Alle,
Ich habe ein Problem und bitte um Hilfe.
Ich generiere jeweils mit DAC über PIN04 und PIN05 zwei Sinussignale am
STM32F407VG- Board , die mit einer Abtastfrequenz von 8 kHz abgetastet
werden.
Ich kämpfe seit längerer Zeit darum, diese Signale mithilfe von I2S und
I2C auf den Audio-Ausgang CS43l22 rauszuschreiben. Ich möchte mir
einfach ganz normal diese 2 Sinuswellen (aufaddiert als Klang zweier
Töne) anhören können.
Hier unten C-Code mit Codec c. dazu:
#include "stm32f4xx_tim.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_spi.h"
#include "stm32f4xx_i2c.h"
#include "main.h"
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define PI 3.14159265
int k = 0;
float fsin_1 = 347.826087;
float fsin_2 = 615.3846154;
int r = 0; //Variable r zum Erfassen der Signallänge vom Sensor
double sin_digital_1 = 0; // digital generiertes Sinussignal von PA04
double sin_digital_2 = 0; // digital generiertes Sinussignal von PA05
double Ts = 0.000125; // die Abtastperiode
// Aktivierung von Ports und mit den dazugehörigen Timern
void rcc_konfigurieren(void){
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
//enables GPIO clock for PortD
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
// Aktivierung von Alternate Function und von DAC
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE)
}
void gpio_konfigurieren(void) {
GPIO_InitTypeDef GPIO_InitStructure;
/*
DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Timer4 für die Abtastperiode Ts
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void DAC_setup(void)
{
DAC_InitTypeDef DAC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
// Der Kanal_1 für PA04 DAC_InitStructure.DAC_Trigger =
DAC_Trigger_T6_TRGO; //DAC_Trigger_None;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude =
DAC_LFSRUnmask_Bits8_0; // 8-Bit Format
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
DAC_Cmd(DAC_Channel_1, ENABLE);
DAC_SoftwareTriggerCmd(DAC_Channel_1, ENABLE);
// Der Kanal_2 für PA05
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude =
DAC_LFSRUnmask_Bits8_0;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_2, &DAC_InitStructure);
DAC_Cmd(DAC_Channel_2, ENABLE);
DAC_SoftwareTriggerCmd(DAC_Channel_2, ENABLE);
}
// Konfiguration der 4 kHz- Abtastfrequenz
void modus_Ts_timer6 (void){
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM6, ENABLE);
TIM_Cmd(TIM6, DISABLE);
TIM_TimeBaseStructure.TIM_Prescaler = 240;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 14;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter =0x0;
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
TIM_Cmd(TIM6, ENABLE);
}
// Trigger Timer
void modus_Ts_timer7 (void){
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM7, ENABLE);
TIM_Cmd(TIM7, DISABLE);
TIM_TimeBaseStructure.TIM_Prescaler = 240;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 14;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter =0x0;
TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM7, TIM_TRGOSource_Update);
TIM_Cmd(TIM7, ENABLE);
}
// TIM4 zum Zählen einzelner Abtastperioden mit Abtastfrequenz = 4
kHz
void timer4_konfigurieren (void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 240;
TIM_TimeBaseStructure.TIM_Period = 14;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
// Das Ergebnis optional auf einen Pin rausschreiben
/* TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 25;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM4, &TIM_OCInitStructure); */
TIM_Cmd( TIM4, ENABLE);
}
void TIM4_IRQHandler(void)
{
static int k1=0;
static int k2=0;
// Festlegung der Amplitude für den Sinus */
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
// Generieren der digitalen Sinussignale
sin_digital_1 = floor (( 90 * sin(2*PI*fsin_1*k1*Ts)))+ 80;
sin_digital_2 = floor (( 90 * sin(2*PI*fsin_2*k2*Ts)))+ 80;
// Ausschreiben der Abtastperioden in die beiden Register -> PIN04
und PIN05 von GPIOA
DAC_SetChannel1Data(DAC_Align_8b_R, sin_digital_1);
DAC_SetChannel2Data(DAC_Align_8b_R, sin_digital_2);
// Hinaufzählen der Laufvariablen beim Generierungsvorgang
// für 347.8260
k1++;
if (k1>= 23) {
k1=0;
}
// für 615.3846
k2++;
if(k2>=13){
k2=0;
} // Pending Bit zurücksetzen
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
}
}
void nvic_konfigurieren(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
SystemInit();
rcc_konfigurieren();
gpio_konfigurieren ();
nvic_konfigurieren();
DAC_setup ();
modus_Ts_timer6 ();
modus_Ts_timer7 ();
timer4_konfigurieren();
codec_init();
codec_ctrl_init();
I2S_Cmd(CODEC_I2S, ENABLE);
while(1)
{
if (SPI_I2S_GetFlagStatus(CODEC_I2S, SPI_I2S_FLAG_TXE))
{
SPI_I2S_SendData(CODEC_I2S, sin_digital_1); //bloßes Reinschreiben
funktioniert nicht!!!
}
}
}
-----------------------------
Codec c (Konfigurationen)
void codec_init()
{
I2S_InitTypeDef I2S_InitType;
I2C_InitTypeDef I2C_InitType;
SPI_InitTypeDef SPI_InitType;
GPIO_InitTypeDef PinInitStruct;
GPIO_StructInit(&PinInitStruct);
//Reset pin as GPIO
PinInitStruct.GPIO_Pin = CODEC_RESET_PIN;
PinInitStruct.GPIO_Mode = GPIO_Mode_OUT;
PinInitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
PinInitStruct.GPIO_OType = GPIO_OType_PP;
PinInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &PinInitStruct);
// I2C pins
PinInitStruct.GPIO_Mode = GPIO_Mode_AF;
PinInitStruct.GPIO_OType = GPIO_OType_OD;
PinInitStruct.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
PinInitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
PinInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &PinInitStruct);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
//enable I2S and I2C clocks
//RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_SPI3,
ENABLE);
RCC_PLLI2SCmd(ENABLE);
// I2S pins
PinInitStruct.GPIO_OType = GPIO_OType_PP;
PinInitStruct.GPIO_Pin = I2S3_SCLK_PIN | I2S3_SD_PIN | I2S3_MCLK_PIN;
GPIO_Init(GPIOC, &PinInitStruct);
PinInitStruct.GPIO_Pin = I2S3_WS_PIN;
GPIO_Init(GPIOB, &PinInitStruct);
//prepare output ports for alternate function
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_SPI3);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_SPI3);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SPI3);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SPI3);
//keep Codec off for now
GPIO_ResetBits(GPIOD, CODEC_RESET_PIN);
// configure I2S port
SPI_I2S_DeInit(CODEC_I2S);
I2S_InitType.I2S_AudioFreq = I2S_AudioFreq_8k;
I2S_InitType.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
I2S_InitType.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitType.I2S_Mode = I2S_Mode_MasterTx;
I2S_InitType.I2S_Standard = I2S_Standard_Phillips;
I2S_InitType.I2S_CPOL = I2S_CPOL_Low;
I2S_Init(CODEC_I2S, &I2S_InitType);
//I2S_Cmd(CODEC_I2S, ENABLE);
// configure I2C port
I2C_DeInit(CODEC_I2C);
I2C_InitType.I2C_ClockSpeed = 100000;
I2C_InitType.I2C_Mode = I2C_Mode_I2C;
I2C_InitType.I2C_OwnAddress1 = CORE_I2C_ADDRESS;
I2C_InitType.I2C_Ack = I2C_Ack_Enable;
I2C_InitType.I2C_AcknowledgedAddress =
I2C_AcknowledgedAddress_7bit;
I2C_InitType.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_Cmd(CODEC_I2C, ENABLE);
I2C_Init(CODEC_I2C, &I2C_InitType);
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.