[软件] 以RA4M2-SENSOR开发板实现迷你型信号发生器

[复制链接]
238|0
jinglixixi 发表于 2025-10-23 17:19 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2025-10-23 19:42 编辑

申请原创
@21小跑堂

实现迷你信号发生器的方法有两种,一种是以硬件的方式,即通过相应功能模块来实现,如AD9833模块就是一可编程波形发生器;另一种则是以软件的方式来实现。
这里介绍的就是一种采用软件方式,来实现的方案,其功能包括:产生指定幅值的信号、可调占空比的信号、三角波、锯齿波、正弦波、余弦波及控制步进电机的正反转节拍信号等。
为便于使用,是以OLED屏为显示器件,来减少引脚的占用。
为配合功能的选择,是使用板载的按键K1K2K3
产生的信号,则是由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所示。
6176068f9efd2b5c12.png
1  所用资源

923668f9efe4757fb.png
6492068f9efeb8624c.png
2  GPIO配置 (输入与输出

8422668f9f0018955c.png
3 定时器配置

6914568f9f01c2341d.png
4  DAC配置

353768f9f03037c50.png
5 串口配置

随后,可用RASC生成相应的KEIL项目工程。

该信号发生器的界面如图6所示,所用字模由工具软件提取其界面如图7所示。
4751268f9f045ddc75.png
6 界面效果

8322168f9f054d0dbc.png
7 提取方式

实现界面效果的程序为:
  1. OLED_Init();
  2. OLED_Clear();
  3. OLED_ShowCHinese(0,0,0);
  4. OLED_ShowCHinese(16,0,1);
  5. OLED_ShowCHinese(32,0,2);
  6. OLED_ShowCHinese(48,0,3);
  7. OLED_ShowCHinese(64,0,4);
  8. OLED_ShowCHinese(80,0,5);
  9. OLED_ShowCHinese(96,0,6);
  10. OLED_ShowString(0,5,"by:jinglixixi",16);
  11. while(R_BSP_PinRead(BSP_IO_PORT_01_PIN_11)==BSP_IO_LEVEL_HIGH);

功能选择的形式及滚动效果如图8至图10所示,为进行功能选择,K1键用于选取下一项、K2键用于选取前一项、K3键用于确认。
4465368f9f08b69e18.png
8 菜单显示

3557068f9f09ba3ad5.png
9 滚动选取

4145168f9f0af3bac0.png
10 滚动效果

菜单选项滚动效果的函数为:
  1. void gui_menu(uint8_t k)
  2. {
  3.          uint8_t i,h;
  4.          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}};
  5.          for(i=0;i<4;i++)
  6.          {
  7.                     h=(k+i)%6;
  8.                     OLED_ShowCHinese(16,i*2,menu_GRAM[h][0]);
  9.                     OLED_ShowCHinese(32,i*2,menu_GRAM[h][1]);
  10.                     OLED_ShowCHinese(48,i*2,menu_GRAM[h][2]);
  11.          }
  12. }

功能选择处理的程序为:
  1. OLED_Clear();                        
  2. j=1;
  3. k=1;
  4. OLED_ShowChar(8,0,'>',16);
  5. while(j)
  6. {
  7.         if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_12)==BSP_IO_LEVEL_LOW)
  8.         {
  9.                 if(k>1) k=k-1;
  10.         }
  11.         if(R_BSP_PinRead(BSP_IO_PORT_00_PIN_13)==BSP_IO_LEVEL_LOW)
  12.         {
  13.                 if(k>7)
  14.                 {
  15.                         k=1;
  16.                 }
  17.                 else        
  18.                 {                                                                        
  19.                         k=k+1;
  20.                 }
  21.         }
  22.         if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_11)==BSP_IO_LEVEL_LOW)
  23.         {
  24.                 j=0;
  25.         }
  26.         p=k-1;
  27.         gui_menu(p);
  28.         OLED_ShowNum(80,0,k,2,16);
  29.         R_BSP_SoftwareDelay (200, BSP_DELAY_UNITS_MILLISECONDS);
  30. }

为进行参数设置,其界面如图11所示。
4592568f9f0f1e0be5.png
11 参数设置界面

参数设置的程序为:
  1. j=1;
  2. k=1;
  3. OLED_Clear();
  4. OLED_ShowString(16,2,"n=",16);
  5. while(j)
  6. {
  7.      if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_12)==BSP_IO_LEVEL_LOW)
  8.      {
  9.           k=k-1;
  10.      }
  11.      if(R_BSP_PinRead(BSP_IO_PORT_00_PIN_13)==BSP_IO_LEVEL_LOW)
  12.      {
  13.           k=k+1;
  14.      }
  15.      if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_11)==BSP_IO_LEVEL_LOW)
  16.      {
  17.           j=0;
  18.      }
  19.      OLED_ShowNum(40,2,k,2,16);
  20.      R_BSP_SoftwareDelay (200, BSP_DELAY_UNITS_MILLISECONDS);                        
  21. }

为了突出直观性的特点,是通过OLED屏来呈现波形的样式。
绘制坐标轴的函数为:
  1. void gui_draw_axis(void)
  2. {
  3.    gui_draw_hline(62,0,120);
  4.    gui_draw_vline(0,0,62);
  5. }

设置输出幅值的程序为:
  1. j=1;
  2. k=0;
  3. o=0;
  4. OLED_ShowString(16,3,"n=0",16);
  5. while(j)
  6. {
  7.                 if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_12)==BSP_IO_LEVEL_LOW)
  8.                 {
  9.                          if(k>1) k=k-1;
  10.                 }
  11.                 if(R_BSP_PinRead(BSP_IO_PORT_00_PIN_13)==BSP_IO_LEVEL_LOW)
  12.                 {
  13.                          k=k+1;
  14.                 }
  15.                 if(R_BSP_PinRead(BSP_IO_PORT_01_PIN_11)==BSP_IO_LEVEL_LOW)
  16.                 {
  17.                          j=0;
  18.                 }                                         
  19.                 if((p==0)&&(o!=k))
  20.                 {
  21.                         k=k%33;
  22.                         h=3;                                                
  23.                         OLED_ShowString(16,h,"n= .  V",16);
  24.                         OLED_ShowNum(32,h,k/10,1,16);
  25.                         OLED_ShowNum(48,h,k%10,1,16);
  26.                         o=k;
  27.                 }
  28.                 if((p==1)&&(o!=k))
  29.                 {
  30.                         k=k%101;
  31.                         h=3;                                                
  32.                         OLED_ShowString(16,h,"n=    %",16);
  33.                         OLED_ShowNum(32,h,k,3,16);
  34.                         o=k;
  35.                 }
  36.                 R_BSP_SoftwareDelay (200, BSP_DELAY_UNITS_MILLISECONDS);                        
  37. }

绘制幅值输出效果的程序为:
  1. for( (i=0;i<=100;i++)
  2. {
  3.           if(k==0) OLED_DrawPoint(i,62-k*1.5,1);
  4. }                        
  5. OLED_Refresh();                                 
  6. if(k>16) h=5;
  7. else h=3;                                                
  8. OLED_ShowString(16,h,"n= .  V",16);
  9. OLED_ShowNum(32,h,k/10,1,16);
  10. OLED_ShowNum(48,h,k%10,1,16);

在设置输出幅值后,其输出效果如图12和图13所示。
7353068f9f163883e8.png
12 输出低幅值电压

3008668f9f179a7a6e.png
13 输出高幅值电压

以设置幅值的程序为基础,可方便地完成占空比设置的程序,其介绍这里从略。

绘制占空比效果的程序为:
  1. for(i=0;i<=100;i++)
  2. {
  3.         if(k==1)
  4.         {
  5.             if(i<u) OLED_DrawPoint(i,22,1);
  6.             else  OLED_DrawPoint(i,62,1);
  7.             if((i==u)||(i==100)) gui_draw_vline(i,22,62);
  8.         }
  9. }        
  10. gui_draw_hline(22,100,120);                                 
  11. OLED_Refresh();                                         
  12. h=0;                                                
  13. OLED_ShowString(16,h,"n=    %",16);
  14. OLED_ShowNum(32,h,k*10,3,16);

在设置占空比后,占空比的调节效果如图14和图15所示。
6945568f9f1a2b399a.png
14 占空比=40%

1076468f9f1b26a2a5.png
15 占空比=80%

绘制锯齿波的程序为:
  1. for(i=0;i<=100;i++)
  2. {
  3.         g=i%50;   
  4.         if(g<49) OLED_DrawPoint(i,62-g,1);
  5.         if(g==0)  gui_draw_vline(i,12,62);
  6. }

其执行效果如图16所示。
2856668f9f1ef1e401.png
16 锯齿波效果

绘制三角波的程序为:
  1. for(i=0;i<=100;i++)
  2. {
  3.          g=(i%25)*2;
  4.          if((i%25)==0) f=(f+1)%2;
  5.          if(f>0) OLED_DrawPoint(i,62-g,1);
  6.          else OLED_DrawPoint(i,12+g,1);                                 
  7. }

其执行效果如图17所示。
8043668f9f21e177b2.png
17 三角波效果

绘制正弦波的数据为:
  1. int values[64]=
  2. {
  3. {0x07FF},{0x08C8},{0x098E},{0x0A51},{0x0B0F},
  4. {0x0BC4},{0x0C71},{0x0D12},{0x0DA7},{0x0E2E},
  5. {0x0EA5},{0x0F0D},{0x0F63},{0x0FA6},{0x0FD7},
  6. {0x0FF5},{0x0FFF},{0x0FF5},{0x0FD7},{0x0FA6},
  7. {0x0F63},{0x0F0D},{0x0EA5},{0x0E2E},{0x0DA7},
  8. {0x0D12},{0x0C71},{0x0BC4},{0x0B0F},{0x0A51},
  9. {0x098E},{0x08C8},{0x07FF},{0x0736},{0x0670},
  10. {0x05AD},{0x04EF},{0x043A},{0x038D},{0x02EC},
  11. {0x0257},{0x01D0},{0x0159},{0x00F1},{0x009B},
  12. {0x0058},{0x0027},{0x0009},{0x0000},{0x0009},
  13. {0x0027},{0x0058},{0x009B},{0x00F1},{0x0159},
  14. {0x01D0},{0x0257},{0x02EC},{0x038D},{0x043A},
  15. {0x04EF},{0x05AD},{0x0670},{0x0736}
  16. };

绘制正弦与余弦波的函数为:
  1. void gui_sin(uint8_t k)
  2. {
  3.           uint16_t i,sj,p;
  4.           for (i = 0 ; i < 128; i++)           
  5.           {
  6.                   if(k==4) sj=values[i/2];                        
  7.                   else
  8.                   {
  9.                                 p=(i/2+16)%64;  
  10.                                 sj=values[p];
  11.                   }
  12.                   sj=sj/80;
  13.                   OLED_DrawPoint(i,63-sj,1);
  14.            }
  15. }

绘制正弦波的程序为:
  1. Gram_clear();                        
  2. gui_draw_axis(1);        
  3. gui_sin(5);                 
  4. OLED_Refresh();

实现正弦与余弦波的效果如图18和图19所示。
8440168f9f27690ba4.png
18 正弦波效果

1838268f9f2873bc91.png
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)

步进电机正反转的驱动程序为:
  1. void zx(int n)
  2. {
  3.   unsigned char X,Y;
  4.   for(X=0;X<64;X++)
  5.   {
  6.      for(Y=0;Y<8;Y++)
  7.      {
  8.          MDL;
  9.          MAH;
  10.          Delay_hms(n);
  11.          MBH;
  12.          Delay_hms(n);
  13.          MAL;
  14.          Delay_hms(n);
  15.          MCH;
  16.          Delay_hms(n);
  17.          MBL;
  18.          Delay_hms(n);
  19.          MDH;
  20.          Delay_hms(n);
  21.          MCL;
  22.          Delay_hms(n);
  23.          MAH;
  24.          Delay_hms(n);
  25.      }
  26.   }
  27. }

  28. void fx(int n)
  29. {
  30.    unsigned char X,Y;
  31.    for(X=0;X<64;X++)
  32.    {
  33.        for(Y=0;Y<8;Y++)
  34.        {
  35.           MDH;
  36.           MAH;
  37.           Delay_hms(n);
  38.           MAL;
  39.           Delay_hms(n);
  40.           MCH;
  41.           Delay_hms(n);
  42.           MDL;
  43.           Delay_hms(n);
  44.           MBH;
  45.           Delay_hms(n);
  46.           MCL;
  47.           Delay_hms(n);
  48.           MAH;
  49.           Delay_hms(n);
  50.           MBL;
  51.           Delay_hms(n);
  52.        }
  53.     }        
  54. }

4726568f9f2b29f0c7.png
20 步进电机控制


波形输出的初始化函数为:
  1. void Wave_Init(void)
  2. {
  3.         err = FSP_SUCCESS;        
  4.         err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
  5.         assert(err == FSP_SUCCESS);
  6.         err = R_GPT_Start(&g_timer0_ctrl);
  7.         assert(err == FSP_SUCCESS);
  8.         err = R_DAC_Open(&g_dac0_ctrl, &g_dac0_cfg);
  9.         assert(err == FSP_SUCCESS);
  10.         err = R_DAC_Start(&g_dac0_ctrl);
  11.         assert(err == FSP_SUCCESS);
  12. }

波形输出的中断处理函数为:
  1. void g_timer0_callback(timer_callback_args_t * p_args)
  2. {
  3.         FSP_PARAMETER_NOT_USED(p_args);
  4.         R_DAC_Write(&g_dac0_ctrl,wave[i++]);
  5.         if(i >= 256) i = 0;
  6. }

至此,就有效地实现了迷你型信号发生器的功能。此外,通过串口还可以指令的方式来控制波形信号的输出。


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

本版积分规则

525

主题

2957

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部