完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
嗨,伙计们,我正在用一个数字式MEMS麦克风录音语音数据,并用DSPIC3FJ128MC804中的DAC1单元播放它,我遇到了一个问题,即将语音数据写入DAC1的数据缓冲器(也从中读取)。在四个16位寄存器中。我猜它们是FIFOs造的。没有关于如何编写和读取这些FIFO的信息,所以我构建了一个for循环,每次我从麦克风上读取数据时,就可以在我的代码中看到这些数据。为了调试数据,我在将数据写入DAC1、DAC1RDAT的正确数据缓冲区之前,添加了一个额外但不必要的步骤,将数据写入变量(Word)。RB12端口被指定为DAC1的右正端口DAC1RP,这是我的示波器连接的地方(也有DAC1RN右负端口)。即使我在Word(0)、Word(1)、Word(2)和Word(3)中获取数据,我也没有看到任何东西被转移到DAC1RDAT,它根据表窗口连续读取零。我还看到RB12没有显示这个范围。我还尝试用for循环将语音数据写到Word(i),在写完之后,我试着用另一个for循环将所有4个数据包读到DAC1RDAT。这也没用。我知道我漏掉了一些很明显的东西,因为在参考手册中没有关于如何写入DAC1RDAT缓冲区的说明。如能提供任何帮助,我将不胜感激。下面是我的一半工作代码。请注意。//ADC中的dspic33fj128mc804记录来自数字麦克风,并使用DACinclude
以上来自于百度翻译 以下为原文 Hi guys, As I was dealing with recording voice data using a Digilent MEMS microphone and playing it back with the DAC1 unit in dspic33fj128mc804, I came across a problem in writing the voice data to DAC1's data buffer (and also reading from it). The DAC1 has Right and Left channel buffers, each made out of four 16-bit registers. I am guessing they are built as FIFOs. There is no info on how to write (and read) to these FIFOs, so I constructed a for-loop to be able to write data every time I read it from the microphone as you see in my code. I added the an extra but unnecessary step in writing data to a variable, Word(i), before transferring it to the Right Data Buffer of DAC1, DAC1RDAT, for debugging purposes. The RB12 port is designated as DAC1's Right Positive Port, DAC1RP, which is where my oscilloscope is connected (there is also DAC1RN-Right Negative port). Even I get data into Word(0), Word(1), Word(2) and Word(3), I don't see anything transferred to DAC1RDAT, which continuously reads zero according to the Watch window. I also see nothing coming out RB12 with the scope. I also tried to write the voice data to Word(i) with a for-loop, and when writing finished I tried to read all 4 data packets to DAC1RDAT with another for-loop. This didn't work either. I know I am missing something very obvious here because there is no instruction on how to write to DAC1RDAT buffer in the reference manual. I would appreciate any help you can provide. Below is my half-working code. Take care. // ADC of dspic33fj128mc804 records from Digilent microphone and plays back using DAC #include // Configuration Register - FOSCSEL #pragma config IESO = 0 // start with a user-selected oscillator at reset #pragma config FNOSC = 7 // select FRC oscillator with Divide-N at reset // Configuration Register - FOSC #pragma config FCKSM = 3 // both clock switching and fail-safe modes are disabled #pragma config IOL1WAY = 1 // allow only one reconfiguration - not applicable here #pragma config OSCIOFNC = 0 // OSCO pin is a general purpose I/O pin #pragma config POSCMD = 3 // primary oscillators are disabled // Configure In-Circuit Programmer, WDT #pragma config ICS = 3 // Program through PGEC1/PGED1 ports #pragma config FWDTEN = 0 // WDT is disabled #define PPSUnLock __builtin_write_OSCCONL(OSCCON & 0xBF) #define PPSLock __builtin_write_OSCCONL(OSCCON | 0x40) unsigned int SPI_Receive () { while(SPI1STATbits.SPITBF == 1); // Wait until the TX buffer is empty due to a prior process SPI1BUF = 0x0000; // When empty, send the junk word (0x0000) to the TX buffer while(SPI1STATbits.SPIRBF == 0); // As junk bits shifts out, valid bits enter from the SDI port // Wait until the RX buffer is full of valid data return SPI1BUF; // When full, read the valid data in RX buffer through SPI1BUF } int main () { // OSCTUN Register OSCTUNbits.TUN = 0; // select FRC = 7.37MHz // CLKDIV Register CLKDIVbits.FRCDIV = 3; // FRCDIVN = FRC/8 = 7.37/8 = 921.25KHz = FOSC and FP = FOSC/2 = 460.62KHz CLKDIVbits.DOZE = 0; // FP = 460.25KHz = FCY CLKDIVbits.DOZEN = 1; // DOZE defines the ratio between cpu and peripheral clocks // SPI configuration MASTER mode sending 16 bits SPI1CON1bits.DISSCK = 0; // Enable the internal SPI clock SPI1CON1bits.DISSDO = 0; // Enable the SPI data output, SDO SPI1CON1bits.MODE16 = 1; // Enable the 16-bit data mode SPI1CON1bits.SSEN = 0; // This unit is not a slave so Slave Select pin is not used SPI1CON1bits.MSTEN = 1; // Enable MASTER mode SPI1CON1bits.SMP = 0; // Sample input at the pos edge when received at the neg edge of SCK SPI1CON1bits.CKE = 1; // SCK edge: Output data changes when SCK goes from ACTIVE to IDLE state SPI1CON1bits.CKP = 0; // SCK polarity: IDLE is low phase and ACTIVE is high phase of SCK SPI1CON1bits.PPRE = 1; // Primary SPI clock pre-scale is 1:1 SPI1CON1bits.SPRE = 7; // Secondary SPI clock pre-scale is 1:1 -> SCK = 460KHz SPI1STATbits.SPIROV = 0; // Clear initial overflow bit in case an overflow condition in SPI1BUF SPI1STATbits.SPIEN = 1; // Enable the SPI interface // Peripheral Pin Select with RP pins PPSUnLock; RPOR4bits.RP8R = 8; // RP8 is for SCK1 (output)) RPINR20bits.SCK1R = 8; // RP8 is for SCK1 (input)) RPINR20bits.SDI1R = 9; // RP9 is for SDI1 RPOR3bits.RP6R = 0; // RP6 is a default pin to be driven manually to generate SS1 RPOR6bits.RP12R = 0; // RP12 is a default pin for DAC1RP PPSLock; // Define digital I/O TRISBbits.TRISB6 = 0; // Configure RB6 as an output for SS TRISBbits.TRISB8 = 0; // Configure RB8 as an output for SCK1 TRISBbits.TRISB9 = 1; // Configure RB9 as an input for SDI1 TRISBbits.TRISB12 = 0; // Configure RB12 as an output for DAC1RP // Configure DAC DAC1CONbits.FORM = 0; // Data format input for DAC1 is unsigned integer DAC1CONbits.DACFDIV = 5; // Divide DAC input clock by 6 DAC1CONbits.DACEN = 1; // Enable DAC DAC1STATbits.ROEN = 1; // Enable right positive channel unsigned int i, Delay, breakpoint; unsigned int Word[4]; while (DAC1STATbits.RFULL != 1) // While the DAC1RDAT buffer is full then { for (i = 0; i < 4; i++) { LATBbits.LATB6 = 0; // Lower SS for object data reception Word = SPI_Receive(); DAC1RDAT = Word; LATBbits.LATB6 = 1; // Raise SS for object data completion for (Delay = 0; Delay < 100; Delay++); // ADC conversion delay } } breakpoint = 1; } |
|
相关推荐
18个回答
|
|
|
|
|
|
第一次FIFO满后,您的代码将退出主程序!如前所述,在发布代码时请使用[code][/code]标记(没有空格)!
以上来自于百度翻译 以下为原文 Your code will exit main the first time the fifo is full! Try while(1) { if (DAC1STATbits.RFULL) while (DAC1STATbits.RFULL); // Wait while the DAC1RDAT buffer is full else for (Delay = 100; Delay; Delay--); // ADC conversion delay only needed when DAC buffer is not full LATBbits.LATB6 = 0; // Lower SS for object data reception DAC1RDAT = SPI_Receive(); LATBbits.LATB6 = 1; // Raise SS for object data completion } And as stated to you before, please use [ code] [ /code] tags (without the spaces) when posting code! |
|
|
|
退后一步,只需要编写一个程序来按照需要快速写入DAC FIFO(可能使用为此提供的中断,或者甚至只是监视(L/R)EMPTY位)。更改值时进行更改。如果可以,则知道DAC部分正常,可以开始添加其余代码。Susan
以上来自于百度翻译 以下为原文 Back off a step and just make a program that writes to the DAC FIFO as fast as is required (possibly using the interrupt that is provided for that purpose or even just monitoring the (L/R)EMPTY bit). An even simpler alternative is to write to the DACxDFLT register and see if you can make the output change when you change the value. If that works then you know the DAC part is OK and you can start adding back the rest of your code. Susan |
|
|
|
嗨,伙计们,抱歉格式化。我不知道。我试过苏珊的建议,语音数据被写到DAC1DFLT缓冲区没有任何问题。本节如下:我也尝试了Simon的建议,并把他的代码添加到主程序中,但是没有写到DAC1RDAT(在Watch窗口中显示所有0),并且我仍然不能从范围上的DAC1RP(RB12)获得任何东西。WO的意思是等待,直到DAC1RDAT缓冲区变空?我从西蒙的代码中了解到代码正在检查RULL位。只要它等于1,代码就不会做任何事情。如果RFULL进入0(DAC1RDAT空),那么SpIxRead()将把数据带到DAC1RDAT。对吗?在D/A路径的剩余部分中,肯定还有其他东西我们完全遗漏了,因为我能够写到DAC1DFLT。还有其他想法吗?小心一切。
以上来自于百度翻译 以下为原文 Hi guys, Sorry about / format. I didn't know. I tried Susan's suggestion and the voice data gets written to DAC1DFLT buffer without any problem. This section is as follows: LATBbits.LATB6 = 0; DAC1DFLT = SPI_Receive(); LATBbits.LATB6 = 1; I also tried Simon's suggestion and added his code to the main program, but nothing gets written to DAC1RDAT (shows all 0 in the Watch window), and I still cannot get anything from DAC1RP (RB12) on the scope. BTW, isn't the piece of code (Simon's) in the while (1)-loop below supposed to mean to wait until DAC1RDAT buffer becomes empty? My understanding from Simon's code is that the code is checking the RFULL bit. As long as it is equal to 1, the code is not going to do anything. If RFULL goes to 0 (DAC1RDAT empty), then SPI_Receive() will bring data to DAC1RDAT. Is that correct? if (DAC1STATbits.RFULL) while (DAC1STATbits.RFULL); // Wait while the DAC1RDAT buffer is full There must be something else we are missing altogether in the remainder of the D/A path since I am able to write to DAC1DFLT. Any other ideas? Take care all. |
|
|
|
嗨,我错过了SFR ACLKCON中DAC时钟的配置。DAC的时钟可能来自-1-辅助振荡器-2-初级振荡器或-3-Fvco(在一些数据表中它被声明为来自Fcy,但我猜Fvco(预分频器之前PLL输出的时钟)是正确的,请看一下配置ACLKCON的数据表。(根据我的观点,我不认为有可能使用FRC作为DAC时钟)编辑:FRC与Pll应该是可能的
以上来自于百度翻译 以下为原文 Hi, I'm missing the configuration of the DAC clock in SFR ACLKCON. The clock for the DAC can come from -1- Auxilary Oscillator -2- Primary Oscillator or -3- Fvco (in some datasheets it is declared to come from Fcy, but I guess Fvco (Clock at output of PLL before prescaler) is right) Please have a look at the datasheet to configure the ACLKCON. (On my opinion I don't see a possibility to use the FRC as DAC clock) edited: FRC with Pll shoud be possible Attached Image(s) |
|
|
|
嗨,Weydert,你可能是对的!在振荡器数据表中,实际上有两个FOSCs:一个来自8—1MUX,产生FP和FCY,另一个变成DAC时钟。内部FRC时钟产生用于主微控制器功能的预期FP和FCY频率。然而,相同的FRC时钟源可以通过PLL获得FVCO,然后用于DAC时钟的FoSC。你需要设置SelaCLK=0来从PLL中选择FoSC,并用APSTLSCR(默认值=256)划分DAC时钟周期。我会尝试这个,看看会发生什么(最后在隧道的末端有一些光)。
以上来自于百度翻译 以下为原文 Hi Weydert, You may be right! I didn't see this. In the oscillator datasheet, there are in fact two FOSCs: one comes from 8-1MUX and creates FP and FCY, and the other becomes the DAC clock. The internal FRC clock generates the intended FP and FCY frequencies for main micro-controller functions. However, the same FRC clock source can go through PLL to obtain FVCO and then FOSC for the DAC clock. You need to set SELACLK = 0 to select FOSC from the PLL, and divide the DAC clock period by APSTSCLR (default = 256). I will try this and see what happens (finally some light at the end of the tunnel). |
|
|
|
灵感来自你以前的线程,我有一个测试与DAC上周。我的时钟是主振荡器(8MHz)与Pll配置为运行在FCY=32兆赫(启动设备与FRC,然后切换时钟;时钟开关必须启用)测试左通道的DAC。在DAC1L中断中,将0x4000和0xC000交替传送到DAC1LDAT。采用振荡器配置,使用FRC与Pll(在实例中用PLL进行FRC的频率计算;仅显示DAC运行),该代码在左通道输出产生正弦波。DAC中的ND滤波将方波输入转换为正弦波输出
以上来自于百度翻译 以下为原文 Inspired by your previous threads I had a test with the DAC last week. My Clock was Primary Oscillator (8MHz) with Pll configured to run at fcy=32MHz (starting up the device with FRC, then switching clock; Clock-switch must be enabled) Testing the left channel of the DAC. Sending alternating 0x4000 and 0xC000 to DAC1LDAT in the DAC1LInterrupt. #include volatile unsigned int Pass; void InitDAC1() { // configure clock for // Fosc=64MHz Fvco=128MHz // Fvco is used according older datasheet ACLKCON=0; //default value ACLKCONbits.SELACLK=0; //Fosc is clock for divider ACLKCONbits.AOSCMD=0b00; //Aux oszillator disabled; ACLKCONbits.APSTSCLR=0b111; //Divide by 1 // clock to DAC module now = 128MHz/1=128MHz //desired DAC sampling frequency = 10kHz //oversampling frequency= 256*10kHz=2,56MHz //128MHz/2,56MHz=50 DAC1CONbits.DACFDIV=50-1; //divide by 50 DAC1CONbits.FORM=0; //unsigned integer DAC1STAT=0; DAC1STATbits.LOEN=1; //enable left channel output DAC1STATbits.LITYPE=1; //left Interrupt type: FIFO empty DAC1DFLT=0x8000; //default value for output _DAC1LIF=0; _DAC1LIE=1; //left channel interrupt enabled Pass=0; DAC1CONbits.DACEN=1; //start DAC } void __attribute__((interrupt, no_auto_psv))_DAC1LInterrupt(void) { _DAC1LIF = 0; //Clear Left Channel Interrupt Flag if (Pass==0) { Pass=1; DAC1LDAT=0x4000; } else { Pass=0; DAC1LDAT=0xC000; } Nop(); Nop(); Nop(); } I adopted the Oscillator-Configuration to use FRC with Pll (Frequency calculation in the example not valid for FRC with Pll; just to show that the DAC runs) #include /* ; setting for fcy=32MHz ; primary oszillator is XT, 8MHz ; desired Fosc = 64MHz ; prior to PLLPOST (100MHz to 200MHz): 2*64MHz=128MHz ; Pll-Postscaler: /2 ->PLLPOST=0 ; PLLPRE: /2 ->PLLPRE=0 ; input of PLL =8MHz/2=4MHz ; output of PLL=128MHz ; 128MHz/4MHz=32 ; PLLDIV=32-2=30 */ #define OSC_MODE_FAST_RC 0 #define OSC_MODE_PRIMARY_PLL 3 #define OSC_MODE_FRC_PLL 1 void SwitchClock() { // first back to FRC __builtin_write_OSCCONH(OSC_MODE_FAST_RC); __builtin_write_OSCCONL(1); while (OSCCONbits.COSC!=OSCCONbits.NOSC); //configure Pll PLLFBDbits.PLLDIV=30; CLKDIVbits.PLLPOST=0; CLKDIVbits.PLLPRE=0; //__builtin_write_OSCCONH(OSC_MODE_PRIMARY_PLL); //for test purpose only: use FRC with Pll __builtin_write_OSCCONH(OSC_MODE_FRC_PLL); __builtin_write_OSCCONL(1); while (OSCCONbits.COSC!=OSCCONbits.NOSC); } This code produced a sine-wave at the left channel output. (Oversampling and filtering in the DAC converts the square-wave input to a sine-wave output) |
|
|
|
嗨,Weydert,谢谢你费尽心思来测试这个。你的解决方案是优雅的:-我接受你所概述的一切,除了你给DAC的时钟。您采取FVCO=128MHz,并在APSTLSCR单元中将该频率除以1,然后将其馈送到DAC。在DAC中,您进一步将128MHz除以50以获得所需的2.56MHz DAC时钟频率。然而,根据图9.1中的数据表,FoCC=64 MHz是唯一被馈送到APSTLSCR单元而不是FVCO=128MHz的信号。在APSTLSCR单元中,FoCC=64 MHz被除以1,然后指向DAC。因此,DACFDIV应该有25(而不是50)来获得2.56MHz DAC时钟。这不正确吗?
以上来自于百度翻译 以下为原文 Hi Weydert, Thank you for going through the trouble to test this. Your solution is elegant :-) I accept everything you outlined here except the clock you are feeding to the DAC. You took FVCO=128MHz and divided this frequency by 1 in the APSTSCLR unit before feeding it to the DAC. In the DAC, you further divided 128MHz by 50 to obtain the desired 2.56MHz DAC clock frequency. However, according to Fig. 9.1 in the datasheet, FOSC= 64MHz is the only signal to be fed to the APSTSCLR unit instead of FVCO=128MHz. In the APSTSCLR unit, FOSC=64MHz is divided by 1, and then directed to the DAC. Therefore, DACFDIV should have been 25 (instead of 50) to get the 2.56MHz DAC clock. Is it not correct? |
|
|
|
是的,你的计算是正确的。另一方面,我的信息是来自DS70291C,与较新的数据表不同。我们必须测量输出频率,看看哪个数据表是正确的。祝你好运。
以上来自于百度翻译 以下为原文 Yes, your calculation is correct. On the other side, my information is from DS70291C which differs from the newer datasheets. We will have to measure the output-frequency to see which datasheet is right. Good luck. |
|
|
|
嗨,Weydert,因为我在这个芯片上做面包,我的采样频率不能超过2.5kHz。逻辑分析仪上的最佳SPI时钟速度约为50kHz。因此,来自麦克风的SPI时钟频率为48 kHz,DAC数据速率约为2.5kHz。与您的10KHz数据速率相比,它稍微短了一点,但是电路板内外的电线扼杀了我的SCK。无论如何,我想问您是否可以看到监视窗口上的DAC1LDAT值????我试着直接写信给DAC1RDAT,什么都没有出现!我使用中断方案,没有向DAC1RDAT写入任何内容,我使用DAC1STAT检查缓冲区状态,并向DAC1RDAT写入整批数据。Nada!每次我看到0x000我做什么。下面是我的带有断点的代码。请原谅简单的尝试写入DAC1RDAT。我只是看不到手表窗口的任何东西。你是否与DAC1LDAT有同样的经历?小心点:
以上来自于百度翻译 以下为原文 Hi Weydert, Because I am bread-boarding this chip, my sampling frequency cannot go beyond 2.5KHz. The best SPI clock speed on the logic analyzer is about 50KHz. So, the SPI clock frequency from the microphone is 48KHz, and the DAC data rate is about 2.5KHz. It is little short compared to your 10KHz data rate, but wires in and out of the breadboard kill my SCK. At any rate, I want to ask you if you could see the value of DAC1LDAT on your Watch window??? I tried to write directly to DAC1RDAT nothing came up! I used the interrupt scheme, nothing got written to DAC1RDAT, I used DAC1STAT to check the buffer status and write a whole bunch of data to DAC1RDAT. Nada! Every time I see 0x0000 whatever I do. Below is my code with breakpoints. Please forgive simple attempts to write to DAC1RDAT. I just cannot see anything in the Watch window. Do you experience the same with DAC1LDAT? Take care :-) #include // Configuration Register - FOSCSEL #pragma config IESO = 0 // start with a user-selected oscillator at reset #pragma config FNOSC = 1 // select FRC oscillator with PLL at reset // Configuration Register - FOSC #pragma config FCKSM = 3 // both clock switching and fail-safe modes are disabled #pragma config OSCIOFNC = 0 // OSCO pin is a general purpose I/O pin #pragma config POSCMD = 3 // primary oscillators are disabled // Configure In-Circuit Programmer, WDT #pragma config ICS = 3 // Program through PGEC1/PGED1 ports #pragma config FWDTEN = 0 // WDT is disabled #define PPSUnLock __builtin_write_OSCCONL(OSCCON & 0xBF) #define PPSLock __builtin_write_OSCCONL(OSCCON | 0x40) unsigned int SPI_Receive () { while(SPI1STATbits.SPITBF == 1); // Wait until the TX buffer is empty due to a prior process SPI1BUF = 0x0000; // When empty, send the junk word (0x0000) to the TX buffer while(SPI1STATbits.SPIRBF == 0); // As junk bits shifts out, valid bits enter from the SDI port // Wait until the RX buffer is full of valid data return SPI1BUF; // When full, read the valid data in RX buffer through SPI1BUF } int main () { // OSCTUN Register OSCTUNbits.TUN = 0; // select FRC = 7.37MHz // CLKDIV Register CLKDIVbits.FRCDIV = 0; // FRCDIVN = FRC/1 = 7.37MHz = FIN CLKDIVbits.PLLPRE = 0; // FIN/2 = 7.37/2 = 3.685MHz CLKDIVbits.PLLPOST = 3; // FRCPLL = 147.4/8 = 18.42MHz = FOSC and FP = 18.42/2 = 9.21MHz CLKDIVbits.DOZE = 0; // FCY = FP/1 = 9.21MHz CLKDIVbits.DOZEN = 1; // DOZE defines the ratio between cpu and peripheral clocks // PLLFBD Register - PLL feedback divisor register PLLFBDbits.PLLDIV = 38; // FVCO = 3.68x40 = 147.4MHz // ACLKCON Register - Auxiliary clock control for DAC ACLKCONbits.SELACLK = 0; // Select PLL output ACLKCONbits.APSTSCLR = 7; // Auxiliary post-scalar to get FA = FOSC/1 = 18.42MHz ACLKCONbits.AOSCMD = 0; // Auxiliary clock is disabled // SPI configuration MASTER mode sending 16 bits SPI1CON1bits.DISSCK = 0; // Enable the internal SPI clock SPI1CON1bits.DISSDO = 0; // Enable the SPI data output, SDO SPI1CON1bits.MODE16 = 1; // Enable the 16-bit data mode SPI1CON1bits.SSEN = 0; // This unit is not a slave so Slave Select pin is not used SPI1CON1bits.MSTEN = 1; // Enable MASTER mode SPI1CON1bits.SMP = 0; // Sample input at the pos edge when received at the neg edge of SCK SPI1CON1bits.CKE = 1; // SCK edge: Output data changes when SCK goes from ACTIVE to IDLE state SPI1CON1bits.CKP = 0; // SCK polarity: IDLE is low phase and ACTIVE is high phase of SCK SPI1CON1bits.PPRE = 0; // Primary SPI clock = 9.21/64 = 143.90KHz SPI1CON1bits.SPRE = 5; // Secondary SPI clock = 143.90/3 = 48KHz - MAX breadboard limit SPI1STATbits.SPIROV = 0; // Clear initial overflow bit in case an overflow condition in SPI1BUF SPI1STATbits.SPIEN = 1; // Enable the SPI interface // Peripheral Pin Select with RP pins PPSUnLock; RPOR4bits.RP8R = 8; // RP8 is for SCK1 (output)) RPINR20bits.SCK1R = 8; // RP8 is for SCK1 (input)) RPINR20bits.SDI1R = 9; // RP9 is for SDI1 RPOR3bits.RP6R = 0; // RP6 is a default pin to be driven manually to generate SS1 RPOR6bits.RP12R = 0; // RP12 is a default pin for DAC1RP PPSLock; // Define digital I/O TRISBbits.TRISB6 = 0; // Configure RB6 as an output for SS TRISBbits.TRISB8 = 0; // Configure RB8 as an output for SCK1 TRISBbits.TRISB9 = 1; // Configure RB9 as an input for SDI1 TRISBbits.TRISB12 = 0; // Configure RB12 as an output for DAC1RP unsigned int Delay, breakpoint; unsigned int i; unsigned int Word[11]; // Store microphone data into memory for (i = 0; i < 11; i++) { LATBbits.LATB6 = 0; // Lower SS for data reception Word = SPI_Receive(); LATBbits.LATB6 = 1; // Raise SS for data completion for (Delay = 0; Delay < 60; Delay++); } // Configure DAC DAC1STAT = 0; // Reset status register DAC1CONbits.DACFDIV = 28; // FDAC = FA/B = 18.42/29 = 635KHz equivalent to DAC sampling rate of 2.5KHz DAC1CONbits.FORM = 0; // Data format input for DAC1 is unsigned integer IFS4bits.DAC1RIF = 0; // Clear right channel interrupt flag IEC4bits.DAC1RIE = 1; // Enable right channel interrupt flag DAC1STATbits.ROEN = 1; // Enable right positive channel DAC1CONbits.DACEN = 1; // Enable DAC // Test DAC1DFLT and DAC1RDAT registers DAC1DFLT = 0x1000; void __attribute__((interrupt, no_auto_psv))_DAC1RInterrupt(void) { IFS4bits.DAC1RIF = 0; //Clear Right Channel Interrupt Flag DAC1RDAT = 0x2000; } breakpoint = 1; // Playback the data stored in memory using DAC i = 0; AGAIN: DAC1RDAT = Word; if (DAC1STATbits.RFULL == 1) // when the Right buffer is full then wait goto WAIT; else { i = i + 1; if (i > 10) goto FINISH; else goto AGAIN; } WAIT: while (DAC1STATbits.REMPTY != 1); // wait here until Right buffer is empty i = i + 1; if (i > 10) goto FINISH; else goto AGAIN; FINISH: breakpoint = 2; } |
|
|
|
我在DAC1LDAT上看到0x0000。可能是因为DAC1LDAT是一个具有4个单词的FIFO,而不是一个简单的寄存器。但是DAC的输出跟随我的数据。你的中断触发了吗?在第一次审判中,我除了做DAC和等待中断外,什么也不做。程序的其余部分只在(1)时进行;如果没有得到中断,我会尝试RITYPE=1(如果FIFO是EMPTY,则中断)。编辑:代码:为什么要在这里插入ISR?我想知道编译器为什么允许这样做。在我的设备上“原样”运行代码会在某个地方产生重置。
以上来自于百度翻译 以下为原文 I see 0x0000 on the DAC1LDAT. Maybe because the DAC1LDAT is a FIFO with 4 words and not a simple register. But the output from the DAC follows my data. Is your interrupt firing? At a first trial I would do nothing else than only setting up the DAC and awaiting the Interrupt. The rest of the program only while(1); And I would try RITYPE=1 (Interrupt if FIFO is EMPTY) if you don't get the interrupt. Edit: Your code: // Test DAC1DFLT and DAC1RDAT registers DAC1DFLT = 0x1000; void __attribute__((interrupt, no_auto_psv))_DAC1RInterrupt(void) { IFS4bits.DAC1RIF = 0; //Clear Right Channel Interrupt Flag DAC1RDAT = 0x2000; } breakpoint = 1; Why do you insert the ISR here? I wonder why the compiler does allow this. Running your code "as it is" on my device produces a reset somewhere. |
|
|
|
关于DAC速率2.5kHz:你听说过Nyquist和香农吗?理论上说,从2.5kHz的采样频率中恢复的最高频率是2.5kHz/2=1.25kHz,不只是麦克风的频率。对于高达20kHz的音频信号,采样频率为44.1kHz。
以上来自于百度翻译 以下为原文 About the DAC rate of 2.5kHz: Have you heard about Nyquist and Shannon ? The theory says that the highest frequency you can recover from 2.5kHz sampling frequency is 2.5kHz/2=1.25kHz Not just the frequency you would expect from your microphone. For audio signals up to 20kHz sampling frequency is typ 44.1kHz |
|
|
|
嗨,Weydert,我想我给你发了一个错误的中断代码。对不起的!在实际的代码中,我从内存中向DAC提供一整堆数据,并检查IFS4寄存器中的DAC1RIF标志何时触发。我的代码采用内部FRC时钟,通过锁相环以大约635KHz产生DAC时钟,该时钟应该产生2.5KHz的采样率。在我的系统中,用于检查右正通道的DAC输出的代码。有三件事情发生:(1)一旦我启用了右通道,DAC1RIF标志就变为1(ROEN=1)。即使我尝试在触发该标志之后立即清除它,但它只是不想被清除。(2)目标在编程之后几乎立即停止,即使有.(1)语句,并且我禁用了看门狗计时器(#pragma config FWDTEN=0)。可能是因为目标停止得很快。下面是包含你的语句的代码。请让我知道我做错了什么,以及如何让这个东西工作。我还不知道函数void_.((中断,no_auto_psv))_DAC1RInterrupt(void)是如何工作的。我找不到任何地方来找出它(它是在参考手册中的例子)。我还在语句周围添加了一个带有goto语句的循环(在这里注释),但是这仍然无法阻止目标停止,因此在范围中看不到任何内容。
以上来自于百度翻译 以下为原文 Hi Weydert, I think I sent you the wrong code for the interrupt. Sorry! In the actual code, I was feeding a whole bunch of data to DAC from the memory and check when the DAC1RIF flag in IFS4 register was firing. My code takes the internal FRC clock, goes through PLL to generate the DAC clock at about 635KHz, which is supposed to generate 2.5KHz sampling rate. I replicated your code in my system to check out the DAC output from the right positive channel with a scope. Three things happen: (1) DAC1RIF flag goes to 1 as soon as I enable the right channel (ROEN =1). Even though I tried to clear this flag right after it fired, it just does not want to be cleared. (2) The target halts almost right after programming even though there is while (1) statement, and I disabled the watchdog timer (#pragma config FWDTEN = 0). (3) I cannot see anything on the scope screen, possibly because the target halts so quickly. Below is the code that includes your statements. Please let me know what I am doing wrong, and how to get this thing working. Take care. PS. I also don't know how the function, void __attribute__((interrupt, no_auto_psv))_DAC1RInterrupt(void), works. I couldn't find it anywhere to figure it out (it is on the example in reference manual though). I also added a loop around your statements with a goto-statement (commented out here), but this still couldn't prevent target from halting, and as a result I couldn't see anything on the scope. // trial file #include // Configuration Register - FOSCSEL #pragma config IESO = 0 // start with a user-selected oscillator at reset #pragma config FNOSC = 1 // select FRC oscillator with PLL at reset // Configuration Register - FOSC #pragma config FCKSM = 3 // both clock switching and fail-safe modes are disabled #pragma config OSCIOFNC = 0 // OSCO pin is a general purpose I/O pin #pragma config POSCMD = 3 // primary oscillators are disabled // Configure In-Circuit Programmer, WDT #pragma config ICS = 3 // Program through PGEC1/PGED1 ports #pragma config FWDTEN = 0 // WDT is disabled #define PPSUnLock __builtin_write_OSCCONL(OSCCON & 0xBF) #define PPSLock __builtin_write_OSCCONL(OSCCON | 0x40) int main () { // OSCTUN Register OSCTUNbits.TUN = 0; // select FRC = 7.37MHz // CLKDIV Register CLKDIVbits.FRCDIV = 0; // FRCDIVN = FRC/1 = 7.37MHz = FIN CLKDIVbits.PLLPRE = 0; // FIN/2 = 7.37/2 = 3.685MHz CLKDIVbits.PLLPOST = 3; // FRCPLL = 147.4/8 = 18.42MHz = FOSC and FP = 18.42/2 = 9.21MHz CLKDIVbits.DOZE = 0; // FCY = FP/1 = 9.21MHz CLKDIVbits.DOZEN = 1; // DOZE defines the ratio between cpu and peripheral clocks // PLLFBD Register - PLL feedback divisor register PLLFBDbits.PLLDIV = 38; // FVCO = 3.68x40 = 147.4MHz // ACLKCON Register - Auxiliary clock control for DAC ACLKCONbits.SELACLK = 0; // Select PLL output ACLKCONbits.APSTSCLR = 7; // Auxiliary post-scalar to get FA = FOSC/1 = 18.42MHz ACLKCONbits.AOSCMD = 0; // Auxiliary clock is disabled // Peripheral Pin Select with RP pins PPSUnLock; RPOR4bits.RP8R = 8; // RP8 is for SCK1 (output)) RPINR20bits.SCK1R = 8; // RP8 is for SCK1 (input)) RPINR20bits.SDI1R = 9; // RP9 is for SDI1 RPOR3bits.RP6R = 0; // RP6 is a default pin to be driven manually to generate SS1 RPOR6bits.RP12R = 0; // RP12 is a default pin for DAC1RP PPSLock; // Define digital I/O TRISBbits.TRISB6 = 0; // Configure RB6 as an output for SS TRISBbits.TRISB8 = 0; // Configure RB8 as an output for SCK1 TRISBbits.TRISB9 = 1; // Configure RB9 as an input for SDI1 TRISBbits.TRISB12 = 0; // Configure RB12 as an output for DAC1RP unsigned int Delay; volatile unsigned int Pass; Pass = 0; // Configure DAC DAC1STAT = 0; // Reset status register DAC1CONbits.DACFDIV = 28; // FDAC = FA/B = 18.42/29 = 635KHz equivalent to DAC sampling rate of 2.5KHz DAC1CONbits.FORM = 0; // Data format input for DAC1 is unsigned integer DAC1STATbits.ROEN = 1; // Enable right positive channel IFS4bits.DAC1RIF = 0; // Clear right channel interrupt flag IEC4bits.DAC1RIE = 1; // Enable right channel interrupt flag DAC1CONbits.DACEN = 1; // Enable DAC // Test DAC output with interrupts void __attribute__((interrupt, no_auto_psv))_DAC1RInterrupt(void) { //START: IFS4bits.DAC1RIF = 0; //Clear Right Channel Interrupt Flag if (Pass == 0) { Pass = 1; DAC1RDAT = 0x4000; } else { Pass = 0; DAC1RDAT = 0xC000; } for (Delay = 0; Delay < 10; Delay++); //goto START; } while (1); } |
|
|
|
我不确定这是不是一个格式化的问题,但是看起来你是在嵌入ISR!n“主”函数!我不相信XC16编译器能够正确地处理这个问题,因为它在调用ISR时可能具有正确的上下文。将ISR单独放在代码的顶层。我还希望DAC一启用就设置IF标志,因为DAC1CON在通电时将全部为零,并且缺省设置为你不能改变RITYPE位,所以当FIFO“未满”时它会触发一个中断,在初始化后会立即中断。不要在ISR中设置延迟-它会把事情搞糟。苏珊
以上来自于百度翻译 以下为原文 I'm not sure if it is a formatting issue but it looks like you are embedding the ISR with!n the 'main' function! I don't believe the XC16 compiler handles that correctly as it may have the correct context when the ISR is called. Put the ISR on its own at the top level of the code. Also I would expect the IF flag to be set as soon as the DAC is enabled as the DAC1CON will be all zeros be default on power up and you don't alter the RITYPE bit so it will trigger an interrupt when the FIFO is 'not full' which it will be immediately after being initialised. Don't put a delay in the ISR - it will just mess things up. Susan |
|
|
|
我同意Aussie Susan:将ISR(中断服务例程;void_.((inter.,no_auto_psv))_DAC1RInterrupt(void))放在main()函数之外。否则,ISR在闪存程序中没有分配到正确的位置,并且当中断触发时,PIC无法找到ISR,它将会找到ISR。重置。我更改了void_.((中断,no_auto_psv))_DAC1RInterrupt(void)的位置。(在主节点上附加移动的易失性无符号int Pass)请复制和粘贴并告知结果。
以上来自于百度翻译 以下为原文 I agree with Aussie Susan: Put the ISR (Interrupt service routine; void __attribute__((interrupt, no_auto_psv))_DAC1RInterrupt(void)) outside the main() function. Otherwise the ISR is not allocated at the right position in flash-program and when the interrupt fires the PIC can't find the ISR and will reset. I changed the position of void __attribute__((interrupt, no_auto_psv))_DAC1RInterrupt(void). (additional moved volatile unsigned int Pass on top of main) Please copy and paste and tell about the result. Attachment(s) Main.c.txt (3.13 KB) - downloaded 70 times |
|
|
|
好的,从您关于_DAC1RInterrupt(void)的问题中,我看到您对中断并不熟悉。当然,您可以完全不这样做。基本代码是Post No.11-.bleDAC1RInter.-填充Word()缓冲区的代码,其中包含一些已知的值——每当使用正确的FIF时,从缓冲区写入值到DAC1RDAT。没有满。
以上来自于百度翻译 以下为原文 Ok, from your question about _DAC1RInterrupt(void) I see you are not familiar with interrupts. Of course you can do all without this. Basic code it the code from Post No.11 -Disable DAC1R Interrupt -fill the Word() buffer with some known values -write values from buffer to DAC1RDAT whenever the Right FIFO is not full. Attachment(s) Main2.c.txt (4.99 KB) - downloaded 70 times |
|
|
|
谢谢你,Weydert。事实上,在我把代码发送给您之后,我意识到我忘记了将中断函数放在main外部。我纠正了它的位置,它起作用了。你是对的,比起中断,我更喜欢使用状态寄存器。在这种情况下,通过轮询状态位,我准确地知道DAC1RDAT是满的还是空的,或者介于两者之间。但是,我不能对中断做同样的处理,因为即使当DAC1打开(ROEN=1),中断也可以触发,或者DAC1RDAT变满或变空等等。在微芯片网站?例如:u.((中断,no_auto_psv))_DAC1RInterrupt(void)我在XC16编译器中搜索它吗?再次感谢。
以上来自于百度翻译 以下为原文 Thank you, Weydert. In fact right after I sent you the code, I realized that I forgot to take the interrupt function outside the main. I corrected its location, and it worked. You are right, I prefer to work with status register than the interrupts. In this particular case, by polling status bits I know exactly if the DAC1RDAT is full, or empty, or somewhere between. However, I cannot do the same with interrupts because the interrupt can fire even when the DAC1 is on (ROEN = 1), or DAC1RDAT becomes full or empty etc. So, I cannot decipher which event is causing the interrupt to take place. Also, one other question: where do the interrupt-related function reside in Microchip website? For example: __attribute__((interrupt, no_auto_psv))_DAC1RInterrupt(void) Am I going to search for it in the XC16 compiler? Thanks again. |
|
|
|
编译器手册将告诉您“u.((中断,no_auto_psv))”是什么意思。您必须检查MCC生成的代码,以查看“_DAC1RInterrupt(void)”做什么。
以上来自于百度翻译 以下为原文 The compiler manual will tell you what "__attribute__((interrupt, no_auto_psv))" means. You will have to examine the code produced by MCC to see what "_DAC1RInterrupt(void)" does. |
|
|
|
只有小组成员才能发言,加入小组>>
5006 浏览 9 评论
1923 浏览 8 评论
1853 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3068 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2144 浏览 5 评论
578浏览 1评论
434浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
477浏览 0评论
368浏览 0评论
IPECMD命令烧录AVR128DA48芯片,报找不到芯片错误
853浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-18 05:44 , Processed in 1.746023 second(s), Total 110, Slave 96 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号