查看: 8263|回复: 22

[求助] 飞思卡尔ADC和OLED显示问题

[复制链接]

该用户从未签到

10

主题

32

帖子

0

注册会员

Rank: 2

积分
142
最后登录
2017-7-28
发表于 2015-12-21 21:04:17 | 显示全部楼层 |阅读模式
本帖最后由 nolanpeers 于 2015-12-21 21:09 编辑

各位大神,好!

我现在用的是MK22FN512这款芯片,用1KHz的采样频率采集10000个点,每16个数送1个数到OLED显示,OLED用的是SPI方式。
请问我如何显示才能不影响采样率,也就是说我将采集到的数值每16个送到OLED显示,第1个到第15个采样值不显示,当第16个采集完后,立即将第16个数送到OLED显示,同时ADC做第17个采样动作,17到31个数不显示,当采集到第32个时,将第32个数送到OLED显示。以此类推。直到10000个点采集结束。可是OLED显示时ADC就会停下来等OLED显示结束才能继续做AD转换,请问有什么好的方法能解决显示和采集互不影响,也就是边采集边显示?  谢谢!
我知道答案 目前已有22人回答
回复

使用道具 举报

  • TA的每日心情
    擦汗
    2016-12-4 23:20
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    9

    主题

    573

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1785
    最后登录
    2017-3-3
    发表于 2015-12-22 09:10:51 | 显示全部楼层
    DMA      
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-5-3 11:19
  • 签到天数: 10 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    50

    主题

    1万

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    14090
    最后登录
    2024-4-19
    发表于 2015-12-22 09:23:05 | 显示全部楼层
    楼上说的对DMA方式。。。 blank.png blank1.png blank2.png blank3.png blank4.png blank5.png blank6.png blank7.png blank8.png blank9.png
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    145

    主题

    4926

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    9267
    最后登录
    1970-1-1
    发表于 2015-12-22 09:30:58 | 显示全部楼层
    本帖最后由 FSL_TICS_ZJJ 于 2015-12-22 09:37 编辑

    楼主放心,你这种需求对时间要求并不高,所以不会影响你的数据采集以及显示。
    采集使用ADC中断采集,然后在中断中取数据存入数组,并做一些相关标志的记录,比如第16个数据置位显示标志。
    然后在主循环中查询显示标志是否需要显示,需要显示,则将数据传入OLED显示。
    ADC使用中断采集,所以不会影响到你的显示,也不会丢失ADC采集数据。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    10

    主题

    32

    帖子

    0

    注册会员

    Rank: 2

    积分
    142
    最后登录
    2017-7-28
     楼主| 发表于 2015-12-22 10:12:29 | 显示全部楼层

    能详细点吗?谢谢!我没做过这块!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    10

    主题

    32

    帖子

    0

    注册会员

    Rank: 2

    积分
    142
    最后登录
    2017-7-28
     楼主| 发表于 2015-12-22 10:14:25 | 显示全部楼层
    FSL_TICS_ZJJ 发表于 2015-12-22 09:30
    楼主放心,你这种需求对时间要求并不高,所以不会影响你的数据采集以及显示。
    采集使用ADC中断采集,然后在 ...

    中断采集好后,送到OLED显示时不是也要占用一些处理时间马,那会不会影响AD采集的采样率呢?是用定时器中断吗?
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    145

    主题

    4926

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    9267
    最后登录
    1970-1-1
    发表于 2015-12-22 12:58:25 | 显示全部楼层
    nolanpeers 发表于 2015-12-22 10:14
    中断采集好后,送到OLED显示时不是也要占用一些处理时间马,那会不会影响AD采集的采样率呢?是用定时器中 ...

    显示就直接在main函数的while(1)里面显示就好了。AD采集是中断,不会影响。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    10

    主题

    32

    帖子

    0

    注册会员

    Rank: 2

    积分
    142
    最后登录
    2017-7-28
     楼主| 发表于 2015-12-22 15:12:00 | 显示全部楼层
    FSL_TICS_ZJJ 发表于 2015-12-22 12:58
    显示就直接在main函数的while(1)里面显示就好了。AD采集是中断,不会影响。 ...

    请教一个弱弱的问题,PIT,PDB,LPTMR有什么区别?还有就是,定时器里面的时间是要根据执行的指令数目来调整吗?也就是考虑到OLED执行显示会占用时间,要不要将定时器时间缩小一点?
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    145

    主题

    4926

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    9267
    最后登录
    1970-1-1
    发表于 2015-12-22 17:10:03 | 显示全部楼层
    nolanpeers 发表于 2015-12-22 15:12
    请教一个弱弱的问题,PIT,PDB,LPTMR有什么区别?还有就是,定时器里面的时间是要根据执行的指令数目来 ...

    你好!
    PIT是周期性中断定时器:是一组可以用于产生中断和触发DMA通道的定时器。
    LPTMR是低功耗定时器,可以被配置为具有可选分频银子的定时器,也可以被配置为带有脉冲干扰滤波的脉冲计数器。可以在5种操作模式下运行,运行模式、等待模式、停止模式、低漏模式和调试模式。
    PDB是可编程延迟模式,可以提供从内部/外部触发源、可编程间隔到AD转换的硬件触发,也可以提供DA转换模块间隔触发的可控延时,这样就可以为ADC转换和DAC输出提供精确的时间。
    定时器的时间是根据它的时钟源来计时的,具体请查看对应芯片的reference manual。
    我不知道你想如何显示OLED,具体显示时间你可以用定时器去控制输出显示。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    10

    主题

    32

    帖子

    0

    注册会员

    Rank: 2

    积分
    142
    最后登录
    2017-7-28
     楼主| 发表于 2015-12-23 15:57:03 | 显示全部楼层
    本帖最后由 nolanpeers 于 2015-12-23 16:05 编辑
    FSL_TICS_ZJJ 发表于 2015-12-22 17:10
    你好!
    PIT是周期性中断定时器:是一组可以用于产生中断和触发DMA通道的定时器。
    LPTMR是低功耗定时器, ...

    非常感谢您的耐心回答!我用例子中的PIT例程进行AD采集,可是我的OLED刷新程序还是会影响采样的频率,我用SPI方式进行刷新,SPI是我用管脚模拟的时序。我设置了一个标志信号,用来判断AD采样率的,如图1,不加入刷新程序,标志管脚的波形如图,频率是1KHz。可能是OLED刷新时间过长导致的,加入刷新程序后波形如图二,空白的地方就是OLED刷新时AD停止采样,此时标志管脚的频率就不是1KHz。我发现问题出在了OLED刷新这一段,每次都要刷新128次,所以用时比较多,刷新代码如下:        
    for(i=0;i<128;i++)
             {
                     for(col=0;col<=7;col++)
                     {
                                    temp[col]=temp[i+1][col];
                                    write_temp(i,col);
                     }
             }
    请问我如何改进?我的主要程序如下:
    请问我如果用SPI模块是不是会好一些?图三中的几个SPI例子有什么区别?我该用哪一个?谢谢!
    int main(void)
    {
        int32_t cnt;
        int32_t row,i=0;
              fp32  x1,x2;
              //uint16_t result;
              uint32_t result;
                    unsigned char c=127;
                    float    DEV_1st[10000];
            
            fp32 a[ORDER+1],b[ORDER+1];
            b[0]=0.000089416; b[1]=0.00026825; b[2]=0.00026825; b[3]=0.000089416; //3.50
            a[0]=1.0000;  a[1]=-2.8157;   a[2]=2.6481;    a[3]=-0.8316;
            fp32 Y_out[Size_1st_Num];

        hardware_init();

        gpio_input_pin_user_config_t inputPin[] = {
            {
                .pinName                       = BOARD_SW_GPIO,  //0x3E
                                              //.pinName                       = test,  //0x3E
                .config.isPullEnable           = true,
    #if FSL_FEATURE_PORT_HAS_PULL_SELECTION//=1
                .config.pullSelect             = kPortPullUp,
    #endif
    #if FSL_FEATURE_PORT_HAS_PASSIVE_FILTER//=1
                .config.isPassiveFilterEnabled = false,
    #endif
    #if FSL_FEATURE_PORT_HAS_DIGITAL_FILTER//=1
                .config.isDigitalFilterEnabled = false,
    #endif
                .config.interrupt              = kPortIntFallingEdge,
            },
            {
                .pinName = GPIO_PINS_OUT_OF_RANGE,
            }
        };

        gpio_output_pin_user_config_t outputPin[] = {
            {
                .pinName              = OLED_SCL,   //0xA
                .config.outputLogic   = 0,
    #if FSL_FEATURE_PORT_HAS_SLEW_RATE//=1
                .config.slewRate      = kPortFastSlewRate,
    #endif
    #if FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH//=1
                .config.driveStrength = kPortHighDriveStrength,
    #endif
            },
            {
                .pinName = GPIO_PINS_OUT_OF_RANGE,
            }
        };
                   

        gpio_output_pin_user_config_t outputPin_2[] = {
            {
                .pinName              = OLED_SDA,   //0xA
                .config.outputLogic   = 0,
    #if FSL_FEATURE_PORT_HAS_SLEW_RATE//=1
                .config.slewRate      = kPortFastSlewRate,
    #endif
    #if FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH//=1
                .config.driveStrength = kPortHighDriveStrength,
    #endif
            },
            {
                .pinName = GPIO_PINS_OUT_OF_RANGE,
            }
        };
                   
        gpio_output_pin_user_config_t outputPin_3[] = {
            {
                .pinName              = OLED_RST,   //0xA
                .config.outputLogic   = 0,
    #if FSL_FEATURE_PORT_HAS_SLEW_RATE//=1
                .config.slewRate      = kPortFastSlewRate,
    #endif
    #if FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH//=1
                .config.driveStrength = kPortHighDriveStrength,
    #endif
            },
            {
                .pinName = GPIO_PINS_OUT_OF_RANGE,
            }
        };

        gpio_output_pin_user_config_t outputPin_4[] = {
            {
                .pinName              = OLED_DC,   //0xA
                .config.outputLogic   = 0,
    #if FSL_FEATURE_PORT_HAS_SLEW_RATE//=1
                .config.slewRate      = kPortFastSlewRate,
    #endif
    #if FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH//=1
                .config.driveStrength = kPortHighDriveStrength,
    #endif
            },
            {
                .pinName = GPIO_PINS_OUT_OF_RANGE,
            }
        };
                   
                   
        gpio_output_pin_user_config_t outputPin_5[] = {
            {
                .pinName              = test,   //0xA
                .config.outputLogic   = 0,
    #if FSL_FEATURE_PORT_HAS_SLEW_RATE//=1
                .config.slewRate      = kPortFastSlewRate,
    #endif
    #if FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH//=1
                .config.driveStrength = kPortHighDriveStrength,
    #endif
            },
            {
                .pinName = GPIO_PINS_OUT_OF_RANGE,
            }
        };
                   
                                    
        // Init LED1, SW1.
        GPIO_DRV_Init(inputPin, outputPin, outputPin_2, outputPin_3,outputPin_4,outputPin_5);
        // Turn LED1 on.
        GPIO_DRV_SetPinOutput(OLED_SCL); //kGpioLED1=0xA
                    GPIO_DRV_SetPinOutput(OLED_SDA);
        GPIO_DRV_SetPinOutput(OLED_DC);
        GPIO_DRV_SetPinOutput(OLED_RST);
        GPIO_DRV_SetPinOutput(test);
            
            
            
        PRINTF("\r\nadc_hw_trigger demo running...\r\n\r\n");

    #ifdef USE_DAC_OUT_AS_SOURCE
        // use DAC to generate the sine wave
        dac_gen_wave();
    #else
        // If no DAC can be use, then a function generator should
        // be used to generate a signal wave, and connect to ADC input
    #endif

            OLED_Init(); //oled 初始化
            //OLED_Fill(0xff); //全屏初始化
            delayms(1000);  
            //OLED_Fill(0x00); //清零

      PRINTF("\r\n press any key to start .... ");
      GETCHAR();

            // initialize the ADC
        if (init_adc(ADC_INST))
        {
            PRINTF("Failed to do the ADC init\n");
            return -1;
        }

        // setup the HW trigger source
        init_trigger_source(ADC_INST);

                    result = ADC16_DRV_GetConvValueRAW(ADC_INST, (uint32_t)gCurChan);
                    result = ADC16_DRV_GetConvValueRAW(ADC_INST, (uint32_t)gCurChan);
        x1=((float)(0xffff&result)*0.0503)/1000;
        for (cnt = 0; cnt <10000; cnt++)
        {

            double tmpRatio;
                              GPIO_DRV_TogglePinOutput(test);//²âÊÔ²ÉÑùÂʱêÖ¾ÐźŠ       

            while (gAdcDone != true)
            {
                                           
                                    }

            result = ADC16_DRV_GetConvValueRAW(ADC_INST, (uint32_t)gCurChan);
            x2=((float)(0xffff&result)*0.0503)/1000;                        
            i++;
                                           
    /*     OLED显示  */
            if(i%16==0)
                    {
                       draw_num(c,x2); //每隔16个数,提取一个数画波形
                       c--;
                       if(c==0)
                         c=127;
                    }

             gAdcDone = false;

        }

        // disable the adc0
        ADC16_DRV_Deinit(ADC_INST);
        // disable hw trigger source
        deinit_trigger_source(ADC_INST);
    //#ifdef USE_DAC_OUT_AS_SOURCE
    //    // disable dac source
    //    dac_stop_wave();
    //#endif

                     while(1)                    {
                                 for(i=0;i<10000;i++)             /* ********   输出所有AD采样值   **********/
                                printf("%-10.5lf",DEV_1st);
                         }

    }

    unsigned char draw_num(unsigned char x,float dat)         //数据到显示格数转换
    {
      unsigned char cache;
            char t;        
            cache=dat/0.13735;
      t=63-cache;
      display_anypoint(x,t);
      return t;
    }
    /*************    OLED显示程序   ***************/
    void display_anypoint(unsigned char x,unsigned char y)
    {
            unsigned char i,row,col;
            
            temp[128][y>>3] = (0xff<<(y%8))&0xff;//
            mid[y>>3]=temp[128][y>>3];
            for(i=7;i>=(y>>3)+1;i--)
             {
                     temp[128]=0xff;
                     mid=temp[128];
             }
            if(x==127)
                    {
                            temp[128][y>>3] = (0x01<<(y%8));
                            for(i=7;i>=(y>>3)+1;i--)
                                    {
                                            temp[128]=0x00;
                                    }
                    }
                   
            else
                    {
                            if((((y>>8)==(data>>8))&&((y%8)==(data%8)))||(x==127))
                                    {
                                            temp[128][y>>3] = (0x01<<(y%8));
                                            for(i=7;i>=(y>>3)+1;i--)
                                                    {
                                                            temp[128]=0x00;
                                                    }
                                    }
                                    
                            else if(y>data)
                                    {
                                            for(i=7;i>=(data>>3);i--)
                                                    {
                                                            temp[128]=temp[128]^mid2;
                                                    }
                                    }
                                    
                            else if((y<data))
                                    {
                                            for(i=7;i>=(data>>3);i--)
                                                    {
                                                            temp[128]=temp[128]^mid2;

                                                    }
                                    }
                    }
            
             
    /* ***********  OLED刷新,每刷新一次后左移一位  实现从左往右显示 **************/        
            for(i=0;i<128;i++)
             {
                     for(col=0;col<=7;col++)
                     {
                                    temp[col]=temp[i+1][col];
                                    write_temp(i,col);
                     }
             }
             
             mid2[y>>3]=now;
             data=y;

             for(i=0;i<=7;i++)
             {
                     mid2=mid;
                     temp[128]=0x00;
             }
             


    }        

    /*********************OLED全屏*************************/
    void OLED_Fill(unsigned char bmp_dat)
    {
    unsigned char y,x;
    for(y=0;y<8;y++)
    {
    OLED_WrCmd(0xb0+y);
    OLED_WrCmd(0x01);
            
    OLED_WrCmd(0x10);
    for(x=0;x<X_WIDTH;x++)
            {
    OLED_WrDat(bmp_dat);
            }
    }
    }

    void write_temp(unsigned char x,unsigned char y)
    {
              OLED_Set_Pos(x,y);
              OLED_WrDat(temp[x][y]);
    }

    void OLED_Set_Pos(unsigned char x, unsigned char y)
    {
            OLED_WrCmd(0xb0+y);
            OLED_WrCmd(((x&0xf0)>>4)|0x10);
            OLED_WrCmd((x&0x0f)|0x00);
    }

    void OLED_WrDat(unsigned char dat)
    {
            uint32_t  i=8;
            unsigned char   data;        
            GPIO_DRV_SetPinOutput(OLED_DC);
            for(i=0;i<8;i++) //·¢ËÍÒ»¸ö°ËλÊý¾Ý
                    {
                            GPIO_DRV_ClearPinOutput(OLED_SCL);  
                            data=dat&0x80;
                            if(data)
                                    GPIO_DRV_SetPinOutput(OLED_SDA);
                            else
                                    GPIO_DRV_ClearPinOutput(OLED_SDA);
                            GPIO_DRV_SetPinOutput(OLED_SCL);            
                            dat<<=1;   
                    }
    }

    void OLED_WrCmd(unsigned char cmd)
    {
    uint32_t i=8;
    unsigned char   SPI_data;
    GPIO_DRV_ClearPinOutput(OLED_DC);
    for(i=0;i<8;i++) //·¢ËÍÒ»¸ö°ËλÊý¾Ý
    {
    GPIO_DRV_ClearPinOutput(OLED_SCL);
    SPI_data=cmd&0x80;
            if(SPI_data)
            {
                    GPIO_DRV_SetPinOutput(OLED_SDA);
            }
            
            else
            {
                    GPIO_DRV_ClearPinOutput(OLED_SDA);
            }
    GPIO_DRV_SetPinOutput(OLED_SCL);
    cmd<<=1;;   
    }
    }


    /*********************OLED初始化刷新************************************/
    void OLED_Init(void)     
    {  
    GPIO_DRV_SetPinOutput(OLED_SCL);
    GPIO_DRV_ClearPinOutput(OLED_RST);
    OLED_DLY_ms(2);
    GPIO_DRV_SetPinOutput(OLED_RST);
           //´ÓÉϵ絽ÏÂÃæ¿ªÊ¼³õʼ»¯ÒªÓÐ×ã¹»µÄʱ¼ä£¬¼´µÈ´ýRC¸´Î»Íê±Ï   
    OLED_WrCmd(0xae);//--turn off oled panel
    OLED_WrCmd(0x00);//---set low column address
    OLED_WrCmd(0x10);//---set high column address
    OLED_WrCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    OLED_WrCmd(0x81);//--set contrast control register
    OLED_WrCmd(0xcf); // Set SEG Output Current Brightness
    OLED_WrCmd(0xa1);//--Set SEG/Column Mapping     0xa0×óÓÒ·´ÖÃ 0xa1Õý³£
    OLED_WrCmd(0xc8);//Set COM/Row Scan Direction   0xc0ÉÏÏ·´Öà 0xc8Õý³£
    OLED_WrCmd(0xa6);//--set normal display
    OLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
    OLED_WrCmd(0x3f);//--1/64 duty
    OLED_WrCmd(0xd3);//-set display offset        Shift Mapping RAM Counter (0x00~0x3F)
    OLED_WrCmd(0x00);//-not offset
    OLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
    OLED_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_WrCmd(0xd9);//--set pre-charge period
    OLED_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_WrCmd(0xda);//--set com pins hardware configuration
    OLED_WrCmd(0x12);
    OLED_WrCmd(0xdb);//--set vcomh
    OLED_WrCmd(0x40);//Set VCOM Deselect Level
    OLED_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
    OLED_WrCmd(0x02);//
    OLED_WrCmd(0x8d);//--set Charge Pump enable/disable
    OLED_WrCmd(0x14);//--set(0x10) disable
    OLED_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
    OLED_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7)
    OLED_WrCmd(0xaf);//--turn on oled panel
    OLED_Fill(0x00);  //³õʼÇåÆÁ
    OLED_Set_Pos(0,0);

    }

    /********************    delayms   ******************/
    void delayms(unsigned int z)
    {
    unsigned int x,y;
    for(x=z; x>0; x--)
    for(y=6848; y>0; y--);
    }

    /*********************OLED ÑÓʱ1ms************************************/
    void OLED_DLY_ms(unsigned int ms)
    {                        
    unsigned int a;
    while(ms)
    {
    a=6800;
    while(a--);
    ms--;
    }
    return;
    }

    /*********************OLED¸´Î»************************************/
    void OLED_CLS(void)
    {
    unsigned char y,x;        
    for(y=0;y<8;y++)
    {
    OLED_WrCmd(0xb0+y);
    OLED_WrCmd(0x01);
    OLED_WrCmd(0x10);
    for(x=0;x<X_WIDTH;x++)
    OLED_WrDat(0);
    }
    }





    图1

    图1

    图2

    图2

    图3

    图3
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-23 13:59 , Processed in 0.112478 second(s), 32 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表