Thông báo

Collapse
No announcement yet.

Lập trình ARM STM32F103x8 để thu tín hiệu ADC 25kHz

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Lập trình ARM STM32F103x8 để thu tín hiệu ADC 25kHz

    Chào cả nhà,
    Em đang lập trình con ARM STM32F103x8 dùng ADC để đọc tín hiệu khoảng 25kHz. Em có đính kèm hình tín hiệu đo bằng oscilloscope. Em lập trình và check thử giá trị đọc được gửi lên máy tính thì kết quả không như mong muốn. Các anh chị xem thử chỉ cho em với. Em cám ơn nhiều ạ!

    https://www.dropbox.com/s/brj55cr4rv...61854.jpg?dl=0
    Code:
    #include "application.h"
    #define ADC1_DR_Address ((uint32_t) 0x4001244c)
    uint16_t ADC_ConvertedValue;
    int myArray[1024];
    int lastTime = 0;
    void setup()
    {
        //Spark.disconnect();
        //WiFi.off();
        
        GPIO_InitTypeDef GPIO_InitStructure;
        DMA_InitTypeDef DMA_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;
        Serial.begin(9600);
        
        //enable ADC1 clock
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        DMA_DeInit(DMA1_Channel1);
        DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &ADC_ConvertedValue;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = 1;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
        DMA_Cmd(DMA1_Channel1, ENABLE);
        
        //ADC1 configuration
        //select independent conversion mode (single)
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
        //We will convert single channel only
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        //We will convert one time
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
        //Select no external triggering
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
        //Right 12-bit data alignment in ADC data register
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        //Single channel conversion
        ADC_InitStructure.ADC_NbrOfChannel = 1;
        //Load structure values to control and status registers
        ADC_Init(ADC1, &ADC_InitStructure);
        
        ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);
        ADC_DMACmd(ADC1, ENABLE);
        //Enable ADC1
        ADC_Cmd(ADC1, ENABLE);
        //Enable ADC1 reset calibration register
        ADC_ResetCalibration(ADC1);
        //Check the end of ADC1 reset calibration register
        while (ADC_GetResetCalibrationStatus(ADC1));
        //Start ADC1 calibration
        ADC_StartCalibration(ADC1);
        //Check the end of ADC1 calibration
        while (ADC_GetCalibrationStatus(ADC1));
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        while (!Serial.available());
    }
    void loop()
    {
        for (int i=0; i<1024; i++)
        {
           ADC_SoftwareStartConvCmd(ADC1, ENABLE);
           while (!DMA_GetFlagStatus(DMA1_FLAG_TC1));
           DMA_ClearFlag(DMA1_FLAG_TC1); 
           myArray[i]=ADC_ConvertedValue;
        }
       // long start = micros();
        if(millis() - lastTime > 1024)
        {
            for (int i=0; i<1024; i++)
            {
                Serial.println(myArray[i]);
            }
            lastTime = millis();
        }
        
       // long end = micros();
        //Serial.println(ADC_ConvertedValue);
        //Serial.print(" micros ");
        //Serial.println(end - start);
        //delay(1000);
    }

  • #2
    Nguyên văn bởi smith2679 Xem bài viết
    Chào cả nhà,
    Em đang lập trình con ARM STM32F103x8 dùng ADC để đọc tín hiệu khoảng 25kHz. Em có đính kèm hình tín hiệu đo bằng oscilloscope. Em lập trình và check thử giá trị đọc được gửi lên máy tính thì kết quả không như mong muốn. Các anh chị xem thử chỉ cho em với. Em cám ơn nhiều ạ!

    https://www.dropbox.com/s/brj55cr4rv...61854.jpg?dl=0
    Code:
    #include "application.h"
    #define ADC1_DR_Address ((uint32_t) 0x4001244c)
    uint16_t ADC_ConvertedValue;
    int myArray[1024];
    int lastTime = 0;
    void setup()
    {
        //Spark.disconnect();
        //WiFi.off();
        
        GPIO_InitTypeDef GPIO_InitStructure;
        DMA_InitTypeDef DMA_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;
        Serial.begin(9600);
        
        //enable ADC1 clock
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        DMA_DeInit(DMA1_Channel1);
        DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &ADC_ConvertedValue;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = 1;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
        DMA_Cmd(DMA1_Channel1, ENABLE);
        
        //ADC1 configuration
        //select independent conversion mode (single)
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
        //We will convert single channel only
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        //We will convert one time
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
        //Select no external triggering
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
        //Right 12-bit data alignment in ADC data register
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        //Single channel conversion
        ADC_InitStructure.ADC_NbrOfChannel = 1;
        //Load structure values to control and status registers
        ADC_Init(ADC1, &ADC_InitStructure);
        
        ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);
        ADC_DMACmd(ADC1, ENABLE);
        //Enable ADC1
        ADC_Cmd(ADC1, ENABLE);
        //Enable ADC1 reset calibration register
        ADC_ResetCalibration(ADC1);
        //Check the end of ADC1 reset calibration register
        while (ADC_GetResetCalibrationStatus(ADC1));
        //Start ADC1 calibration
        ADC_StartCalibration(ADC1);
        //Check the end of ADC1 calibration
        while (ADC_GetCalibrationStatus(ADC1));
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        while (!Serial.available());
    }
    void loop()
    {
        for (int i=0; i<1024; i++)
        {
           ADC_SoftwareStartConvCmd(ADC1, ENABLE);
           while (!DMA_GetFlagStatus(DMA1_FLAG_TC1));
           DMA_ClearFlag(DMA1_FLAG_TC1); 
           myArray[i]=ADC_ConvertedValue;
        }
       // long start = micros();
        if(millis() - lastTime > 1024)
        {
            for (int i=0; i<1024; i++)
            {
                Serial.println(myArray[i]);
            }
            lastTime = millis();
        }
        
       // long end = micros();
        //Serial.println(ADC_ConvertedValue);
        //Serial.print(" micros ");
        //Serial.println(end - start);
        //delay(1000);
    }
    Mình thấy tín hiệu adc ở đầu vào của bạn có vẻ hơi lớn , chân adc của stm32 chỉ đọc đc Vmax <= Vcc(3.3v), nếu lớn hơn sẽ dẫn đến bão hòa (trong hình mình thấy tín hiệu adc phải lớn hơn đến 3 lần chân stm32), khi phục hồi lại thì ra giống xung vuông chứ ko thấy đc biên độ. Mình nghĩ bạn lên giảm tín hiệu adc đầu vào trong giải <= 3V là đẹp nhất.
    (^_^) hoangnv.3i@gmail.com

    Comment


    • #3
      Thanks bạn! Thật ra nếu bạn check góc phải phía dưới của oscilloscope là mình đang dùng thang đo 500mV unit để zoom to ra cho dễ nhìn maximum tín hiệu là ~3V, trung bình là ~2.0V. Mình collect số liệu rồi vẽ thử bằng excel cho ra đồ thị không giống với tín hiệu giống như là ADC setup không đủ nhanh hoặc một lý do nào đó ~~

      Comment


      • #4
        Tốc độ lấy mẫu của ADC thấp .Bạn tăng tốc độ lấy mẫu lên giá trị Max xem.

        Comment


        • #5
          Bạn Post kết quả đo được + chỉnh OSC của bạn về 25uS chú ý phần đầu nhọn
          Các bạn trên diển đàn có hướng giúp cho.
          mình gởi bạn kết quả đo xung vuông ,do tần số lấy mẫu thấp nên các xung hẹp có dạng tam giác.
          Attached Files

          Comment

          Về tác giả

          Collapse

          smith2679 Tìm hiểu thêm về smith2679

          Bài viết mới nhất

          Collapse

          • bqviet
            Trả lời cho Đấu tắt điện cho máy tính bảng
            bởi bqviet
            Bqv cáo lỗi vì chưa đủ khả năng diễn giải để người đọc hiểu. Người làm kỹ thuật sâu đôi khi như thế đó. Về việc nạp pin không vào dù cell mới, khả năng cái mạch quản lý đó đã hỏng - cũng chính là nguyên nhân đám cell cũ hỏng từ đầu.
            06-12-2025, 17:17
          • nguyendinhvan
            Trả lời cho Xin hỏi về mạch thu FM/AM trong catsette
            bởi nguyendinhvan
            Theo tôi, nó chỉ là cái Tuy- ê - nơ, hoặc là khối Trung Văn Tần, nó một phần trong cái Da đì ô thôi. Vì có thấy một chỗ có ba chân hàn, giiống như chân Cờ rít sờ tăng 455 ki nô hẹc. Còn khối Tuy ê nơ thì không nhìn thây cái Di ốt Va di cáp...
            05-12-2025, 19:59
          • afrendly
            Trả lời cho Đấu tắt điện cho máy tính bảng
            bởi afrendly
            Có vẻ ngoài hiểu biết của mình rồi. Cuối cùng mình quyết định tìm mua 2 pin trên Shopee, giá 200K thay vào. Tuy nhận pin được 1%, sạc mãi không vào nhưng cũng mở được máy lên. Vậy cũng tạm. Cảm ơn bạn đã hỗ trợ nhé....
            04-12-2025, 01:27
          • nick22
            Trả lời cho Máy điện châm ?
            bởi nick22
            Đúng như bạn nói, máy điện châm hiện nay trên thị trường đã khá đa dạng về mẫu mã, chức năng và giá thành.
            01-12-2025, 13:23
          Đang tải...
          X