本帖最后由 jinglixixi 于 2025-10-23 19:42 编辑
申请原创 @21小跑堂
实现迷你信号发生器的方法有两种,一种是以硬件的方式,即通过相应功能模块来实现,如AD9833模块就是一种可编程波形发生器;另一种则是以软件的方式来实现。 这里介绍的就是一种采用软件方式,来实现的方案,其功能包括:产生指定幅值的信号、可调占空比的信号、三角波、锯齿波、正弦波、余弦波及控制步进电机的正反转节拍信号等。 为便于使用,是以OLED屏为显示器件,来减少引脚的占用。 为配合功能的选择,是使用板载的按键K1、K2及K3。 产生的信号,则是由DAC引脚输出。至于步进电机的驱动信号,则由其他的引脚输出。 具体的引脚连接关系为: OLED_SCL----P100 OLED_SDA----P101 K1----P013 K2----P112 K3----P111 DAC----P014 TXD9----P109 RXD9----P110 A----P301 B----P302 C----P407 D----P408
相关引脚的配置在RASC下完成,所使用的资源如图1所示,相应资源的配置情况见图2至图5所示。 图1 所用资源
图2 GPIO配置 (输入与输出)
图3 定时器配置
图4 DAC配置
图5 串口配置
随后,可用RASC生成相应的KEIL项目工程。
该信号发生器的界面如图6所示,所用字模由工具软件提取其界面如图7所示。 图6 界面效果
图7 提取方式
实现界面效果的程序为: - OLED_Init();
- OLED_Clear();
- OLED_ShowCHinese(0,0,0);
- OLED_ShowCHinese(16,0,1);
- OLED_ShowCHinese(32,0,2);
- OLED_ShowCHinese(48,0,3);
- OLED_ShowCHinese(64,0,4);
- OLED_ShowCHinese(80,0,5);
- OLED_ShowCHinese(96,0,6);
- OLED_ShowString(0,5,"by:jinglixixi",16);
- while(R_BSP_PinRead(BSP_IO_PORT_01_PIN_11)==BSP_IO_LEVEL_HIGH);
功能选择的形式及滚动效果如图8至图10所示,为进行功能选择,K1键用于选取下一项、K2键用于选取前一项、K3键用于确认。 图8 菜单显示
图9 滚动选取
图10 滚动效果
菜单选项滚动效果的函数为: - void gui_menu(uint8_t k)
- {
- uint8_t i,h;
- uint8_t menu_GRAM[8][3]={{7,8,25},{9,10,11},{12,13,14},{15,16,14},{17,18,14},{19,18,14},{17,21,22},{20,21,22}};
- for(i=0;i<4;i++)
- {
- h=(k+i)%6;
- OLED_ShowCHinese(16,i*2,menu_GRAM[h][0]);
- OLED_ShowCHinese(32,i*2,menu_GRAM[h][1]);
- OLED_ShowCHinese(48,i*2,menu_GRAM[h][2]);
- }
- }
功能选择处理的程序为: - OLED_Clear();
- j=1;
- k=1;
- OLED_ShowChar(8,0,'>',16);
- while(j)
- {
- if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_12)==BSP_IO_LEVEL_LOW)
- {
- if(k>1) k=k-1;
- }
- if(R_BSP_PinRead(BSP_IO_PORT_00_PIN_13)==BSP_IO_LEVEL_LOW)
- {
- if(k>7)
- {
- k=1;
- }
- else
- {
- k=k+1;
- }
- }
- if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_11)==BSP_IO_LEVEL_LOW)
- {
- j=0;
- }
- p=k-1;
- gui_menu(p);
- OLED_ShowNum(80,0,k,2,16);
- R_BSP_SoftwareDelay (200, BSP_DELAY_UNITS_MILLISECONDS);
- }
为进行参数设置,其界面如图11所示。 图11 参数设置界面
参数设置的程序为: - j=1;
- k=1;
- OLED_Clear();
- OLED_ShowString(16,2,"n=",16);
- while(j)
- {
- if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_12)==BSP_IO_LEVEL_LOW)
- {
- k=k-1;
- }
- if(R_BSP_PinRead(BSP_IO_PORT_00_PIN_13)==BSP_IO_LEVEL_LOW)
- {
- k=k+1;
- }
- if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_11)==BSP_IO_LEVEL_LOW)
- {
- j=0;
- }
- OLED_ShowNum(40,2,k,2,16);
- R_BSP_SoftwareDelay (200, BSP_DELAY_UNITS_MILLISECONDS);
- }
为了突出直观性的特点,是通过OLED屏来呈现波形的样式。 绘制坐标轴的函数为: - void gui_draw_axis(void)
- {
- gui_draw_hline(62,0,120);
- gui_draw_vline(0,0,62);
- }
设置输出幅值的程序为: - j=1;
- k=0;
- o=0;
- OLED_ShowString(16,3,"n=0",16);
- while(j)
- {
- if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_12)==BSP_IO_LEVEL_LOW)
- {
- if(k>1) k=k-1;
- }
- if(R_BSP_PinRead(BSP_IO_PORT_00_PIN_13)==BSP_IO_LEVEL_LOW)
- {
- k=k+1;
- }
- if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_11)==BSP_IO_LEVEL_LOW)
- {
- j=0;
- }
- if((p==0)&&(o!=k))
- {
- k=k%33;
- h=3;
- OLED_ShowString(16,h,"n= . V",16);
- OLED_ShowNum(32,h,k/10,1,16);
- OLED_ShowNum(48,h,k%10,1,16);
- o=k;
- }
- if((p==1)&&(o!=k))
- {
- k=k%101;
- h=3;
- OLED_ShowString(16,h,"n= %",16);
- OLED_ShowNum(32,h,k,3,16);
- o=k;
- }
- R_BSP_SoftwareDelay (200, BSP_DELAY_UNITS_MILLISECONDS);
- }
绘制幅值输出效果的程序为: - for( (i=0;i<=100;i++)
- {
- if(k==0) OLED_DrawPoint(i,62-k*1.5,1);
- }
- OLED_Refresh();
- if(k>16) h=5;
- else h=3;
- OLED_ShowString(16,h,"n= . V",16);
- OLED_ShowNum(32,h,k/10,1,16);
- OLED_ShowNum(48,h,k%10,1,16);
在设置输出幅值后,其输出效果如图12和图13所示。 图12 输出低幅值电压
图13 输出高幅值电压
以设置幅值的程序为基础,可方便地完成占空比设置的程序,其介绍这里从略。
绘制占空比效果的程序为: - for(i=0;i<=100;i++)
- {
- if(k==1)
- {
- if(i<u) OLED_DrawPoint(i,22,1);
- else OLED_DrawPoint(i,62,1);
- if((i==u)||(i==100)) gui_draw_vline(i,22,62);
- }
- }
- gui_draw_hline(22,100,120);
- OLED_Refresh();
- h=0;
- OLED_ShowString(16,h,"n= %",16);
- OLED_ShowNum(32,h,k*10,3,16);
在设置占空比后,占空比的调节效果如图14和图15所示。 图14 占空比=40%
图15 占空比=80%
绘制锯齿波的程序为: - for(i=0;i<=100;i++)
- {
- g=i%50;
- if(g<49) OLED_DrawPoint(i,62-g,1);
- if(g==0) gui_draw_vline(i,12,62);
- }
其执行效果如图16所示。 图16 锯齿波效果
绘制三角波的程序为: - for(i=0;i<=100;i++)
- {
- g=(i%25)*2;
- if((i%25)==0) f=(f+1)%2;
- if(f>0) OLED_DrawPoint(i,62-g,1);
- else OLED_DrawPoint(i,12+g,1);
- }
其执行效果如图17所示。 图17 三角波效果
绘制正弦波的数据为: - int values[64]=
- {
- {0x07FF},{0x08C8},{0x098E},{0x0A51},{0x0B0F},
- {0x0BC4},{0x0C71},{0x0D12},{0x0DA7},{0x0E2E},
- {0x0EA5},{0x0F0D},{0x0F63},{0x0FA6},{0x0FD7},
- {0x0FF5},{0x0FFF},{0x0FF5},{0x0FD7},{0x0FA6},
- {0x0F63},{0x0F0D},{0x0EA5},{0x0E2E},{0x0DA7},
- {0x0D12},{0x0C71},{0x0BC4},{0x0B0F},{0x0A51},
- {0x098E},{0x08C8},{0x07FF},{0x0736},{0x0670},
- {0x05AD},{0x04EF},{0x043A},{0x038D},{0x02EC},
- {0x0257},{0x01D0},{0x0159},{0x00F1},{0x009B},
- {0x0058},{0x0027},{0x0009},{0x0000},{0x0009},
- {0x0027},{0x0058},{0x009B},{0x00F1},{0x0159},
- {0x01D0},{0x0257},{0x02EC},{0x038D},{0x043A},
- {0x04EF},{0x05AD},{0x0670},{0x0736}
- };
绘制正弦与余弦波的函数为: - void gui_sin(uint8_t k)
- {
- uint16_t i,sj,p;
- for (i = 0 ; i < 128; i++)
- {
- if(k==4) sj=values[i/2];
- else
- {
- p=(i/2+16)%64;
- sj=values[p];
- }
- sj=sj/80;
- OLED_DrawPoint(i,63-sj,1);
- }
- }
绘制正弦波的程序为: - Gram_clear();
- gui_draw_axis(1);
- gui_sin(5);
- OLED_Refresh();
实现正弦与余弦波的效果如图18和图19所示。 图18 正弦波效果
图19 余弦波效果
为便于步进电机的驱动控制,输出高低电平的语句定义为: #define MAL R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_03_PIN_01, BSP_IO_LEVEL_LOW) #define MAH R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_03_PIN_01, BSP_IO_LEVEL_HIGH) #define MBL R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_03_PIN_02, BSP_IO_LEVEL_LOW) #define MBH R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_03_PIN_02, BSP_IO_LEVEL_HIGH)
#define MCL R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_04_PIN_07, BSP_IO_LEVEL_LOW) #define MCH R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_04_PIN_07, BSP_IO_LEVEL_HIGH) #define MDL R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_04_PIN_08, BSP_IO_LEVEL_LOW) #define MDH R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_04_PIN_08, BSP_IO_LEVEL_HIGH)
步进电机正反转的驱动程序为: - void zx(int n)
- {
- unsigned char X,Y;
- for(X=0;X<64;X++)
- {
- for(Y=0;Y<8;Y++)
- {
- MDL;
- MAH;
- Delay_hms(n);
- MBH;
- Delay_hms(n);
- MAL;
- Delay_hms(n);
- MCH;
- Delay_hms(n);
- MBL;
- Delay_hms(n);
- MDH;
- Delay_hms(n);
- MCL;
- Delay_hms(n);
- MAH;
- Delay_hms(n);
- }
- }
- }
- void fx(int n)
- {
- unsigned char X,Y;
- for(X=0;X<64;X++)
- {
- for(Y=0;Y<8;Y++)
- {
- MDH;
- MAH;
- Delay_hms(n);
- MAL;
- Delay_hms(n);
- MCH;
- Delay_hms(n);
- MDL;
- Delay_hms(n);
- MBH;
- Delay_hms(n);
- MCL;
- Delay_hms(n);
- MAH;
- Delay_hms(n);
- MBL;
- Delay_hms(n);
- }
- }
- }
图20 步进电机控制
波形输出的初始化函数为: - void Wave_Init(void)
- {
- err = FSP_SUCCESS;
- err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
- assert(err == FSP_SUCCESS);
- err = R_GPT_Start(&g_timer0_ctrl);
- assert(err == FSP_SUCCESS);
- err = R_DAC_Open(&g_dac0_ctrl, &g_dac0_cfg);
- assert(err == FSP_SUCCESS);
- err = R_DAC_Start(&g_dac0_ctrl);
- assert(err == FSP_SUCCESS);
- }
波形输出的中断处理函数为: - void g_timer0_callback(timer_callback_args_t * p_args)
- {
- FSP_PARAMETER_NOT_USED(p_args);
- R_DAC_Write(&g_dac0_ctrl,wave[i++]);
- if(i >= 256) i = 0;
- }
至此,就有效地实现了迷你型信号发生器的功能。此外,通过串口还可以指令的方式来控制波形信号的输出。
|