|
|
使用emWin已经有一段时间了,一直没用过GRAPH波形显示控件,前两天无聊,想利用STM32单片机ADC采样,通过GRAPH控件进行显示,看看效果怎么样。 单片机使用的是STM32F103ZET6,它提供了3路独立ADC转换通道,其中ADC1、ADC3支持DMA传输,ADC使用DMA的时候要注意对应的DMA通道号,否则无法进行传输,刚开始在这边浪费了不少时间。同时开启DMA传输完成中断,通过DMA传输中断标志,更新波形数据。 ADC初始化部分代码: - unsigned char DMA1_TransferCompleteFlag = 0, DMA2_TransferCompleteFlag = 0;
- #define ADC1_DR_Address ((uint32_t)0x4001244C)//ADC数据寄存器的基地址
- #define ADC2_DR_Address ((uint32_t)0x4001284C)
- #define ADC3_DR_Address ((uint32_t)0x40013C4C)
-
- //ADC_DR(ADC规则数据寄存器),偏移量=0x4c ADC1(0x40012400-0x400127ff)
- //so ADC1_DR_Address=0x40012400+0x4c
- //==========================================================================================
- unsigned short ADC1ConvertedValue[500];
- unsigned short ADC3ConvertedValue[500];
- unsigned short CH1_Buffer[500];
- unsigned short CH2_Buffer[500];
- void ADC1_Init(void)
- {
- ADC_InitTypeDef ADC_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- DMA_InitTypeDef DMA_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE); //使能ADC和GPIOC时钟
- RCC_ADCCLKConfig(RCC_PCLK2_Div2); //设置ADC分频因子2 72M/2=32,?ADC最大时间不能超过14M
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- DMA_DeInit(DMA1_Channel1); //开启DMA1的第一通道
- DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);//开启中断
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //DMA对应的外设基地址
- DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC1ConvertedValue; //内存存储基地址
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式为SRC模式,由外设搬移到内存
- DMA_InitStructure.DMA_BufferSize = 500; //DMA缓存大小,500个
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //接收一次数据后,目标内存地址后移
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //定义外设数据宽度为16位
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬移数据尺寸,HalfWord就是为16位
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //转换模式,循环缓存模式。
- DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级高
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //M2M模式禁用
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);
- DMA_Cmd(DMA1_Channel1, ENABLE);
-
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
-
- ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; //独立的转换模式
- ADC_InitStructure.ADC_ScanConvMode = DISABLE; //开启扫描模式
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC外部开关,关闭状态
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //对齐方式,ADC为12位中,右对齐方式
- ADC_InitStructure.ADC_NbrOfChannel = 1; //开启通道数,1个
- ADC_Init(ADC1, &ADC_InitStructure);
-
- ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);
- ADC_DMACmd(ADC1, ENABLE); //ADC命令,使能
- ADC_Cmd(ADC1, ENABLE); //开启ADC
- ADC_ResetCalibration(ADC1); //重新校准
- while(ADC_GetResetCalibrationStatus(ADC1)); //等待重新校准完成
- ADC_StartCalibration(ADC1); //开始校准
- while(ADC_GetCalibrationStatus(ADC1)); //等待校准完成
- ADC_SoftwareStartConvCmd(ADC1, ENABLE); //连续转换开始,ADC通过DMA方式不断的更新RAM区。
- }
- void ADC3_Init(void)
- {
- ADC_InitTypeDef ADC_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- DMA_InitTypeDef DMA_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); //使能DMA时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3 | RCC_APB2Periph_GPIOA, ENABLE); //使能ADC和GPIOC时钟
- RCC_ADCCLKConfig(RCC_PCLK2_Div2); //设置ADC分频因子2 72M/2=32,?ADC最大时间不能超过14M
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- DMA_DeInit(DMA2_Channel5); //开启DMA2的第一通道
- DMA_ITConfig(DMA2_Channel5, DMA_IT_TC, ENABLE);//开启中断
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC3_DR_Address; //DMA对应的外设基地址
- DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC3ConvertedValue; //内存存储基地址
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式为SRC模式,由外设搬移到内存
- DMA_InitStructure.DMA_BufferSize = 500; //DMA缓存大小,500个
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //接收一次数据后,目标内存地址后移
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //定义外设数据宽度为16位
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬移数据尺寸,HalfWord就是为16位
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //转换模式,循环缓存模式。
- DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级高
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //M2M模式禁用
- DMA_Init(DMA2_Channel5, &DMA_InitStructure);
- DMA_Cmd(DMA2_Channel5, ENABLE);
-
- NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel4_5_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
-
- ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; //独立的转换模式
- ADC_InitStructure.ADC_ScanConvMode = DISABLE; //开启扫描模式
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC外部开关,关闭状态
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //对齐方式,ADC为12位中,右对齐方式
- ADC_InitStructure.ADC_NbrOfChannel = 1; //开启通道数,1个
- ADC_Init(ADC3, &ADC_InitStructure);
-
- ADC_RegularChannelConfig(ADC3, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);
- ADC_DMACmd(ADC3, ENABLE); //ADC命令,使能
- ADC_Cmd(ADC3, ENABLE); //开启ADC
- ADC_ResetCalibration(ADC1); //重新校准
- while(ADC_GetResetCalibrationStatus(ADC3)); //等待重新校准完成
- ADC_StartCalibration(ADC3); //开始校准
- while(ADC_GetCalibrationStatus(ADC3)); //等待校准完成
- ADC_SoftwareStartConvCmd(ADC3, ENABLE); //连续转换开始,ADC通过DMA方式不断的更新RAM区。
- }
- void DMA1_Channel1_IRQHandler()
- {
- ADC_DMACmd(ADC1, DISABLE); //ADC命令,禁止
- if(DMA_GetITStatus(DMA1_IT_TC1))
- {
- DMA1_TransferCompleteFlag = 1;
- DMA_ClearITPendingBit(DMA1_IT_GL1);
- }
- }
- void DMA2_Channel4_5_IRQHandler()
- {
- ADC_DMACmd(ADC3, DISABLE); //ADC命令,禁止
- if(DMA_GetITStatus(DMA2_IT_TC5))
- {
- DMA2_TransferCompleteFlag = 1;
- DMA_ClearITPendingBit(DMA2_IT_GL5);
- }
- }
获取了ADC数据,接下来就是对数据进行波形显示了。首先需要创建一个小工具hGraph,创建两个数据对象hData[2],分别保存ADC1和ADC3的转化数据,然后将创建的数据附加到小工具hGraph,具体代码如下: - int ChOffset_y[2] = {100, 25};
- #define COLOR_BK GUI_BLACK
- #define COLOR_BORDER GUI_DARKBLUE
- #define COLOR_FRAME GUI_LIGHTCYAN
- #define COLOR_GRID GUI_GRAY
- static GUI_CONST_STORAGE GUI_COLOR _aColorsCh1Arrow[] = {
- 0xFFFFFF, GUI_YELLOW
- };
- static GUI_CONST_STORAGE GUI_COLOR _aColorsCh2Arrow[] = {
- 0xFFFFFF, GUI_GREEN
- };
- static GUI_CONST_STORAGE GUI_COLOR _aChColors[] = {
- GUI_YELLOW, GUI_GREEN
- };
- static GUI_CONST_STORAGE GUI_LOGPALETTE _PalCh1Arrow = {
- 2,
- 1,
- &_aColorsCh1Arrow[0]
- };
- static GUI_CONST_STORAGE GUI_LOGPALETTE _PalCh2Arrow = {
- 2,
- 1,
- &_aColorsCh2Arrow[0]
- };
- static GUI_CONST_STORAGE unsigned char _acp[] = {
- X_______,
- XX______,
- XXXX____,
- XXXXXX__,
- XXXX____,
- XX______,
- X_______,
- };
- static GUI_CONST_STORAGE GUI_BITMAP _Ch1bmp = {
- 8, /* XSize */
- 7, /* YSize */
- 1, /* BytesPerLine */
- 1, /* BitsPerPixel */
- _acp, /* Pointer to picture data (indices) */
- &_PalCh1Arrow /* Pointer to palette */
- };
- static GUI_CONST_STORAGE GUI_BITMAP _Ch2bmp = {
- 8, /* XSize */
- 7, /* YSize */
- 1, /* BytesPerLine */
- 1, /* BitsPerPixel */
- _acp, /* Pointer to picture data (indices) */
- &_PalCh2Arrow /* Pointer to palette */
- };
- static void _UserDraw(WM_HWIN hWin, int Stage) {
- GUI_RECT Rect;
- unsigned short i;
- WM_GetInsideRect(&Rect);
-
- if (Stage == GRAPH_DRAW_LAST) {
- GUI_DrawBitmap(&_Ch1bmp, Rect.x0, Rect.y1-ChOffset_y[0]-30);
- GUI_DrawBitmap(&_Ch2bmp, Rect.x0, Rect.y1-ChOffset_y[1]-30);
- }
- else if (Stage == GRAPH_DRAW_FIRST) {
- GUI_SetColor(COLOR_GRID);
- for (i=Rect.x0+7; i<Rect.x0+7+250; i+=5){//横
- GUI_DrawPixel(i, Rect.y0+12+1);
- GUI_DrawPixel(i, Rect.y0+12+2);
- GUI_DrawPixel(i, Rect.y0+12+25);
- GUI_DrawPixel(i, Rect.y0+12+50);
- GUI_DrawPixel(i, Rect.y0+12+75);
- GUI_DrawPixel(i, Rect.y0+12+99);
- GUI_DrawPixel(i, Rect.y0+12+100);
- GUI_DrawPixel(i, Rect.y0+12+101);
- GUI_DrawPixel(i, Rect.y0+12+125);
- GUI_DrawPixel(i, Rect.y0+12+150);
- GUI_DrawPixel(i, Rect.y0+12+175);
- GUI_DrawPixel(i, Rect.y0+12+199);
- GUI_DrawPixel(i, Rect.y0+12+200);
- }
- for (i=Rect.y0+12; i<Rect.y0+12+200; i+=5){//竖
- GUI_DrawPixel(Rect.x0+7+1, i);
- GUI_DrawPixel(Rect.x0+7+2, i);
- GUI_DrawPixel(Rect.x0+7+25, i);
- GUI_DrawPixel(Rect.x0+7+50, i);
- GUI_DrawPixel(Rect.x0+7+75, i);
- GUI_DrawPixel(Rect.x0+7+100, i);
- GUI_DrawPixel(Rect.x0+7+124, i);
- GUI_DrawPixel(Rect.x0+7+125, i);
- GUI_DrawPixel(Rect.x0+7+126, i);
- GUI_DrawPixel(Rect.x0+7+150, i);
- GUI_DrawPixel(Rect.x0+7+175, i);
- GUI_DrawPixel(Rect.x0+7+200, i);
- GUI_DrawPixel(Rect.x0+7+225, i);
- GUI_DrawPixel(Rect.x0+7+249, i);
- GUI_DrawPixel(Rect.x0+7+250, i);
- }
- }
- }
- #define BUTTON_UNPRESSED_BKCOLOR GUI_DARKGREEN
- #define BUTTON_PRESSED_BKCOLOR GUI_LIGHTGREEN
- #define BUTTON_TEXTCOLOR GUI_WHITE
- void Task_Gui(void *pdata)
- {
- OS_ERR err;
- WM_HWIN hGraph, hItem;
- GRAPH_DATA_Handle hData[2];
- unsigned short threshold_value = 3000;
- unsigned int Xsync=0;
- unsigned int i=0;
- GUI_Init(); //STemWin初始化
- WM_SetDesktopColor(GUI_BLACK);
- WM_SetCreateFlags(WM_CF_MEMDEV);
- hGraph = GRAPH_CreateEx(0, 0, 320, 240, WM_HBKWIN, WM_CF_SHOW | WM_CF_CONST_OUTLINE, 0, 0);
- GRAPH_SetUserDraw(hGraph, _UserDraw);
- GRAPH_SetBorder(hGraph, 8, 13, 320-8-250, 240-13-200);
- WM_SetHasTrans (hGraph);
- WIDGET_SetEffect(hGraph, &WIDGET_Effect_None);
- GRAPH_SetColor (hGraph, COLOR_BK, GRAPH_CI_BK);
- GRAPH_SetColor (hGraph, COLOR_BORDER, GRAPH_CI_BORDER);
- GRAPH_SetColor (hGraph, COLOR_FRAME, GRAPH_CI_FRAME);
- GRAPH_SetColor (hGraph, COLOR_GRID, GRAPH_CI_GRID);
- //GRAPH_SetGridVis (hGraph, 1); //自绘网格线,这里禁止
- //GRAPH_SetLineStyleH(hGraph, GUI_LS_DOT);
- //GRAPH_SetLineStyleV(hGraph, GUI_LS_DOT);
- GRAPH_SetGridDistX(hGraph, 25);
- GRAPH_SetGridDistY(hGraph, 25);
- GRAPH_SetGridFixedX(hGraph, 1);
- for (i=0; i<2; i++) {
- hData[i] = GRAPH_DATA_YT_Create(_aChColors[i], 250, 0, 0);
- GRAPH_AttachData(hGraph, hData[i]);
- GRAPH_DATA_YT_SetOffY(hData[i], ChOffset_y[i]);
- GRAPH_DATA_YT_SetAlign(hData[i], GRAPH_ALIGN_LEFT);
- }
- for (i=0; i<5; i++) {
- hItem = BUTTON_CreateEx(8+250+5,12+i*42,52,34,hGraph, WM_CF_SHOW | WM_CF_CONST_OUTLINE, 0, 0);
- BUTTON_SetTextAlign(hItem, GUI_TA_HCENTER|GUI_TA_VCENTER);
- BUTTON_SetBkColor(hItem, BUTTON_CI_UNPRESSED, BUTTON_UNPRESSED_BKCOLOR);
- BUTTON_SetBkColor(hItem, BUTTON_CI_PRESSED, BUTTON_PRESSED_BKCOLOR);
- BUTTON_SetTextColor(hItem, BUTTON_BI_UNPRESSED, BUTTON_TEXTCOLOR);
- BUTTON_SetTextColor(hItem, BUTTON_BI_PRESSED, BUTTON_TEXTCOLOR);
- BUTTON_SetFocussable(hItem, 0);// Set all buttons non focussable
- WIDGET_SetEffect(hItem, &WIDGET_Effect_None);//1??3DD??
- }
- while(1) {
- GUI_Exec();
- OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);//延时10ms
-
- if (DMA1_TransferCompleteFlag && DMA2_TransferCompleteFlag) {
- DMA2_TransferCompleteFlag = 0;
- DMA1_TransferCompleteFlag = 0;
- for(i=0; i<500; i++) {
- CH1_Buffer[i] = ADC1ConvertedValue[i];
- CH2_Buffer[i] = ADC3ConvertedValue[i];
- }
- ADC_DMACmd(ADC1, ENABLE); //ADC命令,使能
- ADC_DMACmd(ADC3, ENABLE); //ADC命令,使能
-
- for(i=125; i<500-125; i++){
- if (CH1_Buffer[i] < threshold_value &&
- CH1_Buffer[i+1] > threshold_value){
- Xsync = i-125;
- break;
- }
- }
- GRAPH_DATA_YT_Clear(hData[0]);
- GRAPH_DATA_YT_Clear(hData[1]);
- for (i=0; i<250; i++) {//更新hData数据
- GRAPH_DATA_YT_AddValue(hData[0], (((CH1_Buffer[Xsync+i]>>6)*165)>>6)>>1);
- GRAPH_DATA_YT_AddValue(hData[1], (((CH2_Buffer[Xsync+i]>>6)*165)>>6)>>1);
- }
- }
- }
- }
用555搭了个多谐振荡器产生一路信号,然后再RC积分电路产生一路信号,信号频率57K左右,最后显示照片: [ 此帖被inthesun在2016-05-28 22:16重新编辑 ]
|