229|0

172

帖子

3

TA的资源

一粒金砂(高级)

楼主
 

【Follow me第二季第3期】EK-RA6M5简易信号发生器设计汇总 [复制链接]

 

本帖最后由 EPTmachine 于 2025-1-6 22:14 编辑

本次Follow Me活动使用的开发板为Renesas的EK_RA6M5开发板。主要实现以下几个任务。

入门任务:搭建环境,下载调试示例程序,Blink,按键;

基础任务:quad-spi flash和octo-spi flash配置及读写速度测试;DAC配置生成波形及性能测试;

进阶任务:示例程序中新增命令打印信息;

扩展任务:设计一个类似信号发生器功能的例程。可在示例程序上修改。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息。

播放器加载失败: 未检测到Flash Player,请到安装
output

入门任务:

任务相关的内容【Follow me第二季第3期】1入门任务:搭建环境,下载调试示例程序,Blink,按键

入门任务通过调用bsp中的延时函数,实现周期控制,在延时完成后,改变连接LED的IO的输出状态,从事而实现LED灯闪烁的功能。连接按键的IO配置为中断输入,接收外部的中断信号,设置相应的标志变量,在主程序中检测对应的标志变量,改变延时的时间长短,影响LED灯的闪烁频率。程序的流程图如下:

中断程序检测部分代码(位于“button.c中”):

  1. void button1_callback(external_irq_callback_args_t *p_args)
  2. {
  3. /* Make sure it's the right interrupt*/
  4. if(USER_SW1_IRQ_NUMBER == p_args->channel)
  5. {
  6. g_sw1_press = true;
  7. }
  8. }
  9. void button2_callback(external_irq_callback_args_t *p_args)
  10. {
  11. /* Make sure it's the right interrupt*/
  12. if(USER_SW2_IRQ_NUMBER == p_args->channel)
  13. {
  14. g_sw2_press = true;
  15. }
  16. }

主程序中检测按键状态变量和控制LED输出引脚的代码如下(位于“hal_entry.c中”)

  1. while (1)
  2. {
  3. /* Toggle user LED1 when user button1 is pressed*/
  4. if(true == g_sw1_press)
  5. {
  6. /* Clear user button1 flag */
  7. g_sw1_press = false;
  8. /* Read user LED pin */
  9. err = R_IOPORT_PinRead(&g_ioport_ctrl, (bsp_io_port_pin_t)leds.p_leds[0], &led1_level);
  10. /* Handle error */
  11. if (FSP_SUCCESS != err)
  12. {
  13. /* Close External IRQ module.*/
  14. button_deinit();
  15. }
  16. /* Reverse LED pin state*/
  17. led1_level ^= BSP_IO_LEVEL_HIGH;
  18. /* Toggle user LED */
  19. err = R_IOPORT_PinWrite(&g_ioport_ctrl, (bsp_io_port_pin_t)leds.p_leds[0], led1_level);
  20. /* Handle error */
  21. if (FSP_SUCCESS != err)
  22. {
  23. /* Close External IRQ module.*/
  24. button_deinit();
  25. }
  26. }
  27. /* Change user LED2 blink feq when user button2 is pressed*/
  28. if(true == g_sw2_press)
  29. {
  30. /* Clear user button2 flag */
  31. g_sw2_press = false;
  32. switch(feq_level)
  33. {
  34. case slow_speed:
  35. feq_level=normal_speed;
  36. freq_in_hz=1;
  37. break;
  38. case normal_speed:
  39. feq_level=high_speed;
  40. freq_in_hz=2;
  41. break;
  42. case high_speed:
  43. feq_level=slow_speed;
  44. freq_in_hz=5;
  45. break;
  46. }
  47. delay = bsp_delay_units / freq_in_hz;
  48. }
  49. err = R_IOPORT_PinWrite(&g_ioport_ctrl, (bsp_io_port_pin_t)leds.p_leds[1], led2_level);
  50. /* Toggle level for next write */
  51. if (BSP_IO_LEVEL_LOW == led2_level)
  52. {
  53. led2_level = BSP_IO_LEVEL_HIGH;
  54. }
  55. else
  56. {
  57. led2_level = BSP_IO_LEVEL_LOW;
  58. }
  59. /* Delay */
  60. R_BSP_SoftwareDelay(delay, bsp_delay_units);
  61. }

工程的效果如图

e2studio的开发环境功能多样,在熟悉各部分功能的使用后,可以借助FSP工具、Deverlop Asssitant代码提示加快开发进度。

基础任务:

任务相关的内容【Follow me第二季第三期】基础任务:quad spi、octo spi、dac和定时器使用

板载的外设很多,quad spi flash和octo spi flash扩展了开发板的存储空间,可以存储更多的程序和数据,实现复杂的应用,同时FSP配置工具中可以快捷地设定相关外设的驱动代码,方便外设的使用减少开发人员的工作量。

测量quad spi flash和octo spi flash 的基本思路为:

相关的代码如下(位于gpt_timer.c中):

  1. fsp_err_t start_gpt_timer (timer_ctrl_t * const p_timer_ctl)
  2. {
  3. fsp_err_t err = FSP_SUCCESS;
  4. /* Starts GPT timer */
  5. err = R_GPT_Start(p_timer_ctl);
  6. if (FSP_SUCCESS != err)
  7. {
  8. /* In case of GPT_open is successful and start fails, requires a immediate cleanup.
  9. * Since, cleanup for GPT open is done in start_gpt_timer,Hence cleanup is not required */
  10. APP_ERR_PRINT ("\r\n ** R_GPT_Start API failed ** \r\n");
  11. }
  12. return err;
  13. }
  14. void report_timer_count(void)
  15. {
  16. fsp_err_t err = FSP_SUCCESS;
  17. timer_status_t timer_info;
  18. uint32_t time_counter=0;
  19. err=stop_gpt_timer (&g_timer_ctrl);
  20. err=get_gpt_timer_status(&g_timer_ctrl,&timer_info);
  21. err=reset_gpt_timer (&g_timer_ctrl);
  22. time_counter=timer_info.counter;
  23. APP_PRINT("\nOperation on Flash Completed Successfully,Time Cost: %d ticks under %d HZ \r\n",time_counter,timer_freq);
  24. }

实际运行时,可以得到OSPI在SPI模式、SOPI、DOPI模式下的读写操作耗时。通过Segger RTT工具输出的定时器计数频率在100MHz时,读写4096字节数据的测试信息如下。

SPI模式下写时间耗时3.26ms,读时间耗时5.1ms

SOPI模式下写时间耗时2.6ms,读时间耗时1.6ms

DOPI模式下写时间耗时2.5ms,读时间耗时1.5ms

使用DAC输出方波,配置DAC和定时器,在定时器中断中改变DAC输出寄存器的值,从而输出周期为定时器频率一半的方波,大致的流程如下:

主函数中对定时器和DAC进行初始化(位于“hal_entry.c中”)

  1. /* Open the DAC channel */
  2. err = R_DAC_Open (&g_dac1_ctrl, &g_dac1_cfg);
  3. /* Write value to DAC module */
  4. err = R_DAC_Write (&g_dac1_ctrl, DAC_MIN_VAL);
  5. /* Start DAC conversion */
  6. err = R_DAC_Start (&g_dac1_ctrl);
  7. /*Initialize Periodic Timer */
  8. err = init_gpt_timer(&g_timer0_ctrl, &g_timer0_cfg);
  9. /* Start Periodic Timer*/
  10. err = start_gpt_timer(&g_timer0_ctrl);

回调函数每次调用会修改DAC的数据寄存器中的值,改变DAC输出的电压值,从而生成方波。(位于“gpt_timer.c中”)

  1. void timer0_callback(timer_callback_args_t *p_args)
  2. {
  3. /* TODO: add your own code here */
  4. if(TIMER_EVENT_CYCLE_END==p_args->event)
  5. {
  6. if(dac_output==DAC_MIN_VAL)
  7. {
  8. dac_output=DAC_MAX_VAL;
  9. }
  10. else if(dac_output==DAC_MAX_VAL)
  11. {
  12. dac_output=DAC_MIN_VAL;
  13. }
  14. R_DAC_Write (&g_dac1_ctrl,dac_output);
  15. }
  16. }

使用示波器采集输出端的信号,得到的是500Hz,幅值为3.3V的方波。

进阶任务:

任务相关的内容【Follow me第二季第三期】进阶任务:通过USB发送指令修改QSPI中的数据

USB设备可以设定端点类型为CDC设备,从而实现与电脑的通讯,建立通讯后后,通过控制台向开发板发送数据,从而实现数据交互和指令控制。

根据接受到的数据的不同,提示用户输入相关的输入,从而实现对qspi flash中存储的数据的修改。

示例程序的流程图如下

添加指令的核心在与添加可以被识别的菜单选项(menu option),指令的识别和执行的流程图如下:

实现上述功能的代码在工程的menu_dds_record.c和menu_dds_record.h中,其中的dds_record_menu()为处理Flash中数据的具体流程

  1. test_fn dds_record_menu(void)
  2. {
  3. int8_t c = -1;
  4. bool_t valid_dds_index = false;
  5. bool_t valid_dds_type = false;
  6. bool_t valid_dds_freq = false;
  7. int32_t block_sz_ndx = 0;
  8. int32_t block_sz_limit = (INPUT_BUFFER - 2);
  9. uint8_t dds_index;
  10. uint8_t dds_type;
  11. uint32_t dds_freq;
  12. uint32_t value=0;
  13. sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
  14. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  15. print_to_console((void*)s_print_buffer);
  16. sprintf (s_print_buffer, MODULE_NAME, g_selected_menu);
  17. print_to_console((void*)s_print_buffer);
  18. for(uint8_t index=0;index<10;index++)
  19. {
  20. sprintf(s_print_buffer,"\r\n%d.type:%d, freq:%lu, amp:%d, offset:%d", index,
  21. dds_record_ins.dds_items[index].waveType,
  22. dds_record_ins.dds_items[index].freq,
  23. dds_record_ins.dds_items[index].amp,
  24. dds_record_ins.dds_items[index].offset);
  25. print_to_console((void*)s_print_buffer);
  26. }
  27. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  28. sprintf (s_print_buffer, DDSINDEX_OPTIONS);
  29. print_to_console((void*)s_print_buffer);
  30. while (false == valid_dds_index)
  31. {
  32. /* Reset input state */
  33. c = -1;
  34. block_sz_ndx = 0;
  35. memset(&s_block_sz_str, 0, INPUT_BUFFER);
  36. while ((CONNECTION_ABORT_CRTL != c))
  37. {
  38. c = input_from_console();
  39. if (block_sz_ndx < block_sz_limit)
  40. {
  41. /* Cast to req type */
  42. s_block_sz_str[block_sz_ndx] = (char_t)c;
  43. block_sz_ndx++;
  44. }
  45. else
  46. {
  47. /* maximum block size exceeded (4 digits / characters entered) */
  48. s_block_sz_str[block_sz_ndx] = MENU_ENTER_RESPONSE_CRTL;
  49. c = MENU_ENTER_RESPONSE_CRTL;
  50. break;
  51. }
  52. if (MENU_EXIT_CRTL == c)
  53. {
  54. /* Abort the test */
  55. valid_dds_index = true;
  56. dds_index = 0;
  57. break;
  58. }
  59. if (MENU_ENTER_RESPONSE_CRTL == c)
  60. {
  61. break;
  62. }
  63. if (CARRAGE_RETURN != c)
  64. {
  65. /* Cast for req type */
  66. sprintf(s_print_buffer, "%c", (char_t)c);
  67. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  68. print_to_console((void*)s_print_buffer);
  69. }
  70. }
  71. /* If the input was terminated with a TAB then attempt to process it */
  72. if (MENU_ENTER_RESPONSE_CRTL == c)
  73. {
  74. value = validate_user_input(&s_block_sz_str[0]);
  75. }
  76. vTaskDelay(10);
  77. dds_index=(uint8_t)value;
  78. switch (value)
  79. {
  80. default:
  81. {
  82. valid_dds_index = true;
  83. }
  84. }
  85. }
  86. sprintf (s_print_buffer, DDSTYPE_OPTIONS,dds_index);
  87. print_to_console((void*)s_print_buffer);
  88. while (false == valid_dds_type)
  89. {
  90. /* Reset input state */
  91. c = -1;
  92. block_sz_ndx = 0;
  93. memset(&s_block_sz_str, 0, INPUT_BUFFER);
  94. while ((CONNECTION_ABORT_CRTL != c))
  95. {
  96. c = input_from_console();
  97. if (block_sz_ndx < block_sz_limit)
  98. {
  99. /* Cast to req type */
  100. s_block_sz_str[block_sz_ndx] = (char_t)c;
  101. block_sz_ndx++;
  102. }
  103. else
  104. {
  105. /* maximum block size exceeded (4 digits / characters entered) */
  106. s_block_sz_str[block_sz_ndx] = MENU_ENTER_RESPONSE_CRTL;
  107. c = MENU_ENTER_RESPONSE_CRTL;
  108. break;
  109. }
  110. if (MENU_EXIT_CRTL == c)
  111. {
  112. /* Abort the test */
  113. valid_dds_type = true;
  114. dds_type = 0;
  115. break;
  116. }
  117. if (MENU_ENTER_RESPONSE_CRTL == c)
  118. {
  119. break;
  120. }
  121. if (CARRAGE_RETURN != c)
  122. {
  123. /* Cast for req type */
  124. sprintf(s_print_buffer, "%c", (char_t)c);
  125. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  126. print_to_console((void*)s_print_buffer);
  127. }
  128. }
  129. /* If the input was terminated with a TAB then attempt to process it */
  130. if (MENU_ENTER_RESPONSE_CRTL == c)
  131. {
  132. value = validate_user_input(&s_block_sz_str[0]);
  133. }
  134. vTaskDelay(10);
  135. dds_type=(uint8_t)value;
  136. switch (value)
  137. {
  138. default:
  139. {
  140. valid_dds_type = true;
  141. }
  142. }
  143. }
  144. sprintf (s_print_buffer, DDSFREQ_OPTIONS,dds_index);
  145. print_to_console((void*)s_print_buffer);
  146. while (false == valid_dds_freq)
  147. {
  148. /* Reset input state */
  149. c = -1;
  150. block_sz_ndx = 0;
  151. memset(&s_block_sz_str, 0, INPUT_BUFFER);
  152. while ((CONNECTION_ABORT_CRTL != c))
  153. {
  154. c = input_from_console();
  155. if (block_sz_ndx < block_sz_limit)
  156. {
  157. /* Cast to req type */
  158. s_block_sz_str[block_sz_ndx] = (char_t)c;
  159. block_sz_ndx++;
  160. }
  161. else
  162. {
  163. /* maximum block size exceeded (4 digits / characters entered) */
  164. s_block_sz_str[block_sz_ndx] = MENU_ENTER_RESPONSE_CRTL;
  165. c = MENU_ENTER_RESPONSE_CRTL;
  166. break;
  167. }
  168. if (MENU_EXIT_CRTL == c)
  169. {
  170. /* Abort the test */
  171. valid_dds_freq = true;
  172. dds_freq = 0;
  173. break;
  174. }
  175. if (MENU_ENTER_RESPONSE_CRTL == c)
  176. {
  177. break;
  178. }
  179. if (CARRAGE_RETURN != c)
  180. {
  181. /* Cast for req type */
  182. sprintf(s_print_buffer, "%c", (char_t)c);
  183. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  184. print_to_console((void*)s_print_buffer);
  185. }
  186. }
  187. /* If the input was terminated with a TAB then attempt to process it */
  188. if (MENU_ENTER_RESPONSE_CRTL == c)
  189. {
  190. value = validate_user_input(&s_block_sz_str[0]);
  191. }
  192. vTaskDelay(10);
  193. dds_freq=value;
  194. switch (value)
  195. {
  196. default:
  197. {
  198. valid_dds_freq = true;
  199. }
  200. }
  201. }
  202. dds_record_ins.dds_items[dds_index].waveType=dds_type;
  203. dds_record_ins.dds_items[dds_index].freq=dds_freq;
  204. dds_record_ins.dds_items[dds_index].offset=0;
  205. dds_record_ins.dds_items[dds_index].amp=30;
  206. for(uint8_t index=0;index<10;index++)
  207. {
  208. sprintf(s_print_buffer,"\r\n%d.type:%d, freq:%ld, amp:%d, offset:%d", index,
  209. dds_record_ins.dds_items[index].waveType,
  210. dds_record_ins.dds_items[index].freq,
  211. dds_record_ins.dds_items[index].amp,
  212. dds_record_ins.dds_items[index].offset);
  213. print_to_console((void*)s_print_buffer);
  214. }
  215. xSemaphoreGive(g_store_dds_semaphore);
  216. sprintf(s_print_buffer, MENU_RETURN_INFO);
  217. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  218. print_to_console((void*)s_print_buffer);
  219. while ((CONNECTION_ABORT_CRTL != c))
  220. {
  221. if ((MENU_EXIT_CRTL == c) || (0x00 == c))
  222. {
  223. break;
  224. }
  225. c = input_from_console();
  226. }
  227. return (0);
  228. }

在menu_main中定义了如何进行指令的识别和执行,s_menu_items中包含上述两个回调函数,当用户输入正确的数字,程序就会调用相应的回调函数,实现对应的功能。

  1. /* Table of menu functions */
  2. static st_menu_fn_tbl_t s_menu_items[] =
  3. {
  4. {"Text display" , text_display_menu},
  5. {"DDS record edit" , dds_record_menu},
  6. {"", NULL }
  7. };
  8. ...
  9. while ((0 != c))
  10. {
  11. c = input_from_console ();
  12. if (0 != c)
  13. {
  14. /* Cast, as compiler will assume calc is int */
  15. c = (int8_t) (c - '0');
  16. g_selected_menu = c;
  17. if ((c > 0) && (c <= menu_limit))
  18. {
  19. s_menu_items[c - 1].p_func ();
  20. break;
  21. }
  22. }
  23. }

工程编译并下载后,效果运行的效果如下所示。能够对Flash中存储的数据进行读写管理。

扩展任务:

任务相关的内容【Follow me第二季第三期】扩展任务:设计一个类似信号发生器功能的例程

结合之前的qspi flash储存和usb 指令任务,添加dds模块后,即可以实现简易的DDS信号发生器。

程序逻辑上分为指令解析执行和DDS信号产生和输出。

指令解析执行的流程为:

指令解析执行部分的代码大部分与进阶任务相同,这里不多做介绍,其中不同的是DDS数据的选择并产生波形,代码位于menu_dds_ctrl.c

  1. test_fn dds_ctrl_menu(void)
  2. {
  3. int8_t c = -1;
  4. uint8_t dds_index=0;
  5. bool_t valid_dds_index = false;
  6. int32_t block_sz_ndx = 0;
  7. int32_t block_sz_limit = (INPUT_BUFFER - 2);
  8. uint32_t value=0;
  9. dds_param_t cur_dds;
  10. sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
  11. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  12. print_to_console((void*)s_print_buffer);
  13. sprintf (s_print_buffer, MODULE_NAME, g_selected_menu);
  14. print_to_console((void*)s_print_buffer);
  15. for(uint8_t index=0;index<10;index++)
  16. {
  17. sprintf(s_print_buffer,"\r\n%d.type:%d, freq:%lu, amp:%d, offset:%d", index,
  18. dds_record_ins.dds_items[index].waveType,
  19. dds_record_ins.dds_items[index].freq,
  20. dds_record_ins.dds_items[index].amp,
  21. dds_record_ins.dds_items[index].offset);
  22. print_to_console((void*)s_print_buffer);
  23. }
  24. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  25. sprintf (s_print_buffer, DDSINDEX_SELECT);
  26. print_to_console((void*)s_print_buffer);
  27. while (false == valid_dds_index)
  28. {
  29. /* Reset input state */
  30. c = -1;
  31. block_sz_ndx = 0;
  32. memset(&s_block_sz_str, 0, INPUT_BUFFER);
  33. while ((CONNECTION_ABORT_CRTL != c))
  34. {
  35. c = input_from_console();
  36. if (block_sz_ndx < block_sz_limit)
  37. {
  38. /* Cast to req type */
  39. s_block_sz_str[block_sz_ndx] = (char_t)c;
  40. block_sz_ndx++;
  41. }
  42. else
  43. {
  44. /* maximum block size exceeded (4 digits / characters entered) */
  45. s_block_sz_str[block_sz_ndx] = MENU_ENTER_RESPONSE_CRTL;
  46. c = MENU_ENTER_RESPONSE_CRTL;
  47. break;
  48. }
  49. if (MENU_EXIT_CRTL == c)
  50. {
  51. /* Abort the test */
  52. valid_dds_index = true;
  53. dds_index = 0;
  54. break;
  55. }
  56. if (MENU_ENTER_RESPONSE_CRTL == c)
  57. {
  58. break;
  59. }
  60. if (CARRAGE_RETURN != c)
  61. {
  62. /* Cast for req type */
  63. sprintf(s_print_buffer, "%c", (char_t)c);
  64. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  65. print_to_console((void*)s_print_buffer);
  66. }
  67. }
  68. /* If the input was terminated with a TAB then attempt to process it */
  69. if (MENU_ENTER_RESPONSE_CRTL == c)
  70. {
  71. value = validate_user_input(&s_block_sz_str[0]);
  72. }
  73. vTaskDelay(10);
  74. dds_index=(uint8_t)value;
  75. switch (value)
  76. {
  77. default:
  78. {
  79. valid_dds_index = true;
  80. }
  81. }
  82. }
  83. cur_dds=dds_record_get(dds_index);
  84. DDS_setWaveParams(cur_dds.freq, 30, 0, cur_dds.waveType);
  85. sprintf (s_print_buffer, DDS_GEN);
  86. print_to_console((void*)s_print_buffer);
  87. sprintf(s_print_buffer, MENU_RETURN_INFO);
  88. /* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
  89. print_to_console((void*)s_print_buffer);
  90. while ((CONNECTION_ABORT_CRTL != c))
  91. {
  92. if ((MENU_EXIT_CRTL == c) || (0x00 == c))
  93. {
  94. break;
  95. }
  96. c = input_from_console();
  97. }
  98. return (0);
  99. }

其中的DDS_setWaveParams(cur_dds.freq, 30, 0, cur_dds.waveType);即为DDS信号产生和输出的函数。

DDS信号产生和输出的流程为:

相关的代码位于dds.c中,函数DDS_setWaveParams()用于产生DDS信号,getNewWaveLUT()用于生成查找表

  1. void DDS_setWaveParams(uint32_t freq, uint8_t amptitude, int8_t offset, uint8_t type)
  2. {
  3. /* Variable to help handle error codes from functions */
  4. fsp_err_t fsp_err = FSP_SUCCESS;
  5. // Stop DAC DMA Transfer, and leave TIM2 running, that's fine
  6. fsp_err=R_GPT_Stop(&g_timer_dds_ctrl);
  7. R_DMAC_Disable(&g_dma_dds_ctrl);
  8. // Select wave type and update it
  9. switch(type)
  10. {
  11. case SINE_WAVE:
  12. dds.waveType = SINE_WAVE;
  13. break;
  14. case SQUARE_WAVE:
  15. dds.waveType = SQUARE_WAVE;
  16. break;
  17. case TRIANGLE_WAVE:
  18. dds.waveType = TRIANGLE_WAVE;
  19. break;
  20. default:
  21. break;
  22. }
  23. dds.freq = freq;
  24. dds.amp = amptitude;
  25. // Select frequency range and register timer's parameters
  26. if (freq >= 100 && freq < 1000)
  27. {
  28. // FMCLK = 100kHz, 100M / 2000 * 2 = 100kHz
  29. R_GPT_PeriodSet(&g_timer_dds_ctrl, 1000-1);
  30. dds.lutLen = (uint32_t)(100000 / freq);
  31. getNewWaveLUT(dds.lutLen, dds.waveType, dds.amp, dds.offset);
  32. }
  33. else if (freq >= 1000 && freq < 10000)
  34. {
  35. // FMCLK = 1MHz, 100M / 200 * 2 = 1MHz
  36. R_GPT_PeriodSet(&g_timer_dds_ctrl, 100-1);
  37. dds.lutLen = (uint32_t)(1000000 / freq);
  38. getNewWaveLUT(dds.lutLen, dds.waveType, dds.amp, dds.offset);
  39. }
  40. else if (freq >= 10000 && freq < 100000)
  41. {
  42. // FMCLK = 2MHz, 100M / 100 * 2 = 2MHz
  43. R_GPT_PeriodSet(&g_timer_dds_ctrl, 50-1);
  44. dds.lutLen = (uint32_t)(2000000 / freq);
  45. getNewWaveLUT(dds.lutLen, dds.waveType, dds.amp, dds.offset);
  46. }
  47. // Restart DAC DMA Transfer
  48. g_dma_dds_cfg.p_info->length=dds.lutLen;
  49. g_dma_dds_cfg.p_info->p_src=dds_lut;
  50. g_dma_dds_cfg.p_info->p_dest=&g_dac0_ctrl.p_reg->DADR[g_dac0_ctrl.channel_index];
  51. R_DMAC_Reconfigure(&g_dma_dds_ctrl, g_dma_dds_cfg.p_info);
  52. R_DMAC_Enable(&g_dma_dds_ctrl);
  53. //HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)dds_lut, dds.lutLen/2, DAC_ALIGN_12B_R);
  54. R_GPT_Start(&g_timer_dds_ctrl);
  55. if (dds.enable)
  56. {
  57. }
  58. }
  59. void getNewWaveLUT(uint32_t length, uint8_t type, uint8_t amp, int8_t offset)
  60. {
  61. uint16_t a_offset_value = DAC_AMP - (int32_t)DAC_AMP * offset / DDS_MAX_AMP;
  62. if (type == SINE_WAVE)
  63. {
  64. float sin_step = 2.0f * 3.14159f / (float)(length-1);
  65. for (uint16_t i = 0; i < length; i++)
  66. {
  67. dds_lut<i> = (uint16_t)(a_offset_value - (DAC_AMP * sinf(sin_step*(float)i) * amp / DDS_MAX_AMP));
  68. }
  69. }
  70. else if (type == SQUARE_WAVE)
  71. {
  72. for(uint16_t i = 0; i < length / 2; i++)
  73. {
  74. dds_lut<i> = a_offset_value - DAC_AMP * amp / DDS_MAX_AMP;
  75. dds_lut[i + (length / 2)] = a_offset_value + DAC_AMP * amp / DDS_MAX_AMP;
  76. }
  77. }
  78. else if (type == TRIANGLE_WAVE)
  79. {
  80. uint16_t tri_step = DAC_AMP * 2 * amp / DDS_MAX_AMP / (length/2);
  81. for(uint16_t i = 0; i < length / 2; i++)
  82. {
  83. dds_lut<i> = a_offset_value - DAC_AMP * amp / DDS_MAX_AMP + tri_step*i;
  84. dds_lut[length - i - 1] = dds_lut<i>;
  85. }
  86. }
  87. }

实验效果:

产生正弦波

产生方波

产生三角波

总结

开发板的硬件资源和示例代码很多,方便开发者理解如何使用芯片的功能。同时e2studio的开发工具辅助开发者快速搭建应用程序,加快开发进度。

任务代码:

FollowMeEK-RA6M5.7z

(4.23 MB, 下载次数: 3)

点赞 关注
 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
立即报名 | 2025 瑞萨电子工业以太网技术日即将开启!
3月-4月 深圳、广州、北京、苏州、西安、上海 走进全国6城
2025瑞萨电子工业以太网技术巡回沙龙聚焦工业4.0核心需求,为工程师与企业决策者提供实时通信技术最佳解决方案。
预报从速,好礼等您拿~

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表