求教:串口绘图器相关-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 353|回复: 0

[未解决] 求教:串口绘图器相关

[复制链接]
发表于 2022-6-21 13:52 | 显示全部楼层 |阅读模式
本帖最后由 sckocn 于 2022-6-21 15:43 编辑

在网上找到一个函数信号发生器代码。
想用arduino自带的串口绘图器显示调制的波形不知如何修改。
望请高手赐教。
***这段只修改成实时量程,希望修改成实时输出波形

  1. Serial.println(frq); //波形量程输出至串口绘图器
复制代码


以下是完整代码
  1. /***************可调频率信号发生器*******************
  2. * 适用于cpu运行在16MHz的Arduino Uno或Nano
  3. *
  4. * 需要元件:
  5. * Arduino Uno或Nano开发板一块
  6. * 带开关五脚旋转编码器:
  7. *        GND   D10
  8. *         |    |
  9. *      |___________|
  10. *        |   |   |
  11. *       D9  GND  D8
  12. *  调节方法:顺时针增加频率,逆时针减小频率,按压开关改变调节步长
  13. * LCD 1602引脚:RS:D2;RW:GND;EN:D3;数据口4~7:D4~D7;用以显示当前的输出频率和调节步长
  14. * 100K或以上的电位器,用于调节LCD 1602的对比度
  15. * 无源蜂鸣器(可选)一脚接D11,一脚接地;调节频率超范围时会发声
  16. *
  17. * 输出引脚:A0~A7,在一个周期内,前半周期A0、A2、A4、A6高电平,A1、A3、A5、A7低电平;后半个周期则正好相反
  18. *          可以单个引脚配合地线使用,也可以相邻两个引脚一起使用
  19. *          注:国产Nano的A6和A7脚没有输出。
  20. * 输出频率:1Hz~80KHz;初始输出1KHz信号,调节步长10Hz
  21. *
  22. * 为了输出频率范围有较大跨度,程序定义了高频和低频两种模式,因而显得较为复杂
  23. * 高频模式下,按cpu的频率16M计数,一个时钟同期为1/16,000,000秒
  24. * 低频模式下,按cpu频率/256来计数,一个时钟周期为256/16,000,000秒
  25. * ICR1为16位寄存器,可存储0~65535之间的数,计数器在每个时钟周期增加1,当数值与ICR1中数值相等时重置为零,
  26. * 同时触发程序中的ISR()中断,所以改变ICR1的值可以改变输出频率
  27. *
  28. *                      “无线电实验室” 2020年6月1日
  29. *****************************************************/
  30. #include<LiquidCrystal.h>

  31. const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7; //LCD1602引脚定义
  32. LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

  33. const int SW = 10, CW = 9, ACW = 8; //旋转编码器引脚:按键、顺时针、逆时针
  34. int PIN[2] ={CW,ACW};
  35. bool oldState[2];

  36. bool mode = 1;    //高频械式1,低频模式0; 500Hz~80KHz对应高频模式,1~500Hz为低频模式

  37. float STEP = 10;    //初始频率调节步长,可选值为:0.1、1、10、100、1000
  38. float frq = 1000;  //初始输出信号频率,可选范围 1Hz~80KHz
  39. float temp;
  40. byte TP = 0b01010101;

  41. void setup() {
  42.   Serial.begin(9600);       //定义Arduino 串口输出
  43.   initInterrupt();          //初始化中断设置
  44.   DDRC = 0xFF;              //将A0~A7均设为输出模式
  45.   pinMode(SW,INPUT_PULLUP);
  46.   pinMode(PIN[0],INPUT_PULLUP);
  47.   pinMode(PIN[1],INPUT_PULLUP);
  48.   oldState[0]=digitalRead(PIN[0]);
  49.   oldState[1]=digitalRead(PIN[1]);
  50.   lcd.begin(16,2);
  51.   lcd.print("Freq:");
  52.   lcd.print(frq);
  53.   lcd.setCursor(0,1);
  54.   lcd.print("Step:");
  55.   lcd.print(STEP);
  56.   
  57. }

  58. void loop() {
  59.   Serial.println(frq); //波形量程输出至串口绘图器
  60.   if(isChanged(0))//判断为顺时针旋转时
  61.   {
  62.     frq +=STEP;
  63.     if(frq>=500 && mode==0)//需要更改分频模式的情况
  64.     {
  65.       TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 0<<CS11 | 1<<CS10; //高频模式,分频器1
  66.       mode = 1;
  67.     }
  68.     if(frq>80000){
  69.       frq = 80000;
  70.       tone(11,600,50);  //最高80KHz,超出量程播放提示音
  71.     }
  72.     temp = 31250/frq*(1+255*mode);
  73.     ICR1 = int(temp);
  74.     TCNT1=0;
  75.     lcd.setCursor(5,0);
  76.     lcd.print(frq);
  77.     lcd.print("      ");
  78.     delay(1);
  79.   }
  80.   if(isChanged(1))//判断为逆时针旋转编码器
  81.   {
  82.     frq -= STEP;
  83.     if(frq<500 && mode==1)//需要改为低频模式的情况
  84.     {
  85.       TCCR1B = 1<<WGM13 | 1<<WGM12 | 1<<CS12 | 0<<CS11 | 0<<CS10;   //低频模式,分频器256
  86.       mode = 0;
  87.     }
  88.     if(frq<1){
  89.       frq = 1;
  90.       tone(11,600,50);//频率最低1Hz,超出时发出滴的声音
  91.     }
  92.     temp = 31250/frq*(1+255*mode);
  93.     ICR1 = int(temp);
  94.     TCNT1=0;
  95.     lcd.setCursor(5,0);
  96.     lcd.print(frq);
  97.     lcd.print("       ");
  98.     delay(1);
  99.   }
  100.   //判断按键是否按下
  101.   if(!digitalRead(SW)){
  102.     delay(140);
  103.     if(!digitalRead(SW)){
  104.       STEP*=10;
  105.       if(STEP>1000)
  106.         STEP=0.1;
  107.     }
  108.     lcd.setCursor(5,1);
  109.     lcd.print(STEP);
  110.     lcd.print("      ");
  111.   }
  112. }

  113. //判断iPin脚电平是否变化,是返回1,否则返回0
  114. bool isChanged(int iPin){   
  115.   bool newState = digitalRead(PIN[iPin]);
  116.   if(newState!=oldState[iPin]){
  117.     oldState[0]=newState;
  118.     oldState[1]=newState;
  119.     return 1;
  120.   }
  121.   else
  122.     return 0;
  123. }

  124. void initInterrupt(){
  125.   TCCR1A = 0;     //普通模式
  126.   TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 0<<CS11 | 1<<CS10; //CTC模式:ICR1触发,初始分频:cpu主频16MHz
  127.   ICR1 = int(8000000/frq);         //寄存器,计数器达到该值时产生中断信号
  128.   TIMSK1 |= 1<<ICIE1;   //允许捕捉事件中断
  129. }

  130. //中断函数
  131. ISR(TIMER1_CAPT_vect){
  132.   TP = ~TP;
  133.   PORTC = TP;
  134. }
复制代码


电路:
c5d0d890d4a8a4cc9e9d4424babd4aa3.png



参考:(比如这个代码LOOP)

  1. float x=0;
  2. float y=0;
  3. const float pi=3.14;
  4. int z=0;
  5. float v=0;
  6. int w=0;
  7. boolean OK=true;
  8. void setup() {
  9. Serial.begin(9600);
  10. }
  11. // the loop function runs over and over again forever
  12. void loop() {
  13. if (w==0){
  14. v=x*pi/180; // making deg in radians
  15. y=sin(v); //calculate sinus
  16. z=y*250; // calculate duty cycle(250 not 255 because will help to turn off transistors)
  17. delay(100);
  18. if(OK==true){
  19. x=x+0.689;// increase the angle
  20. }
  21. }
  22. if (x>90){
  23. OK=false;
  24. }
  25. if (OK==false){
  26. x=x-0.689; //decreasing the angle for the other half
  27. }
  28. Serial.println(z);// on the serial monitor will appear duty cycles between 0 and 180 deg
  29. }
复制代码


代码添加后(二合一)

  1. /***************可调频率信号发生器*******************
  2. * 适用于cpu运行在16MHz的Arduino Uno或Nano
  3. *
  4. * 需要元件:
  5. * Arduino Uno或Nano开发板一块
  6. * 带开关五脚旋转编码器:
  7. *        GND   D10
  8. *         |    |
  9. *      |___________|
  10. *        |   |   |
  11. *       D9  GND  D8
  12. *  调节方法:顺时针增加频率,逆时针减小频率,按压开关改变调节步长
  13. * LCD 1602引脚:RS:D2;RW:GND;EN:D3;数据口4~7:D4~D7;用以显示当前的输出频率和调节步长
  14. * 100K或以上的电位器,用于调节LCD 1602的对比度
  15. * 无源蜂鸣器(可选)一脚接D11,一脚接地;调节频率超范围时会发声
  16. *
  17. * 输出引脚:A0~A7,在一个周期内,前半周期A0、A2、A4、A6高电平,A1、A3、A5、A7低电平;后半个周期则正好相反
  18. *          可以单个引脚配合地线使用,也可以相邻两个引脚一起使用
  19. *          注:国产Nano的A6和A7脚没有输出。
  20. * 输出频率:1Hz~80KHz;初始输出1KHz信号,调节步长10Hz
  21. *
  22. * 为了输出频率范围有较大跨度,程序定义了高频和低频两种模式,因而显得较为复杂
  23. * 高频模式下,按cpu的频率16M计数,一个时钟同期为1/16,000,000秒
  24. * 低频模式下,按cpu频率/256来计数,一个时钟周期为256/16,000,000秒
  25. * ICR1为16位寄存器,可存储0~65535之间的数,计数器在每个时钟周期增加1,当数值与ICR1中数值相等时重置为零,
  26. * 同时触发程序中的ISR()中断,所以改变ICR1的值可以改变输出频率
  27. *
  28. *                      “无线电实验室” 2020年6月1日
  29. *****************************************************/
  30. <b>//绘图器相关定义-Add</b>
  31. <font color="#9932cc">float x=0;
  32. float y=0;
  33. const float pi=3.14;
  34. int z=0;
  35. float v=0;
  36. int w=0;
  37. boolean OK=true;</font>

  38. //原代码
  39. #include<LiquidCrystal.h>

  40. const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7; //LCD1602引脚定义
  41. LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

  42. const int SW = 10, CW = 9, ACW = 8; //旋转编码器引脚:按键、顺时针、逆时针
  43. int PIN[2] ={CW,ACW};
  44. bool oldState[2];

  45. bool mode = 1;    //高频械式1,低频模式0; 500Hz~80KHz对应高频模式,1~500Hz为低频模式

  46. float STEP = 10;    //初始频率调节步长,可选值为:0.1、1、10、100、1000
  47. float frq = 1000;  //初始输出信号频率,可选范围 1Hz~80KHz
  48. float temp;
  49. byte TP = 0b01010101;

  50. void setup() {
  51.   Serial.begin(9600);       //定义Arduino 串口输出波特率
  52.   initInterrupt();          //初始化中断设置
  53.   DDRC = 0xFF;              //将A0~A7均设为输出模式
  54.   pinMode(SW,INPUT_PULLUP);
  55.   pinMode(PIN[0],INPUT_PULLUP);
  56.   pinMode(PIN[1],INPUT_PULLUP);
  57.   oldState[0]=digitalRead(PIN[0]);
  58.   oldState[1]=digitalRead(PIN[1]);
  59.   lcd.begin(16,2);
  60.   lcd.print("Freq:");
  61.   lcd.print(frq);
  62.   lcd.setCursor(0,1);
  63.   lcd.print("Step:");
  64.   lcd.print(STEP);
  65.   
  66. }

  67. void loop() {

  68. <b>//绘图器相关-Add</b>
  69. <font color="#9932cc">{
  70. if (w==0){
  71. v=x*pi/180; // making deg in radians
  72. y=sin(v); //calculate sinus
  73. z=y*250; // calculate duty cycle(250 not 255 because will help to turn off transistors)
  74. delay(100);
  75. if(OK==true){
  76. x=x+0.689;// increase the angle
  77. }
  78. }
  79. if (x>90){
  80. OK=false;
  81. }
  82. if (OK==false){
  83. x=x-0.689; //decreasing the angle for the other half
  84. }
  85. Serial.println(z,frq); //波形量程输出至串口绘图器
  86. }</font>
  87. //原代码
  88.    if(isChanged(0))//判断为顺时针旋转时
  89.   {
  90.     frq +=STEP;
  91.     if(frq>=500 && mode==0)//需要更改分频模式的情况
  92.     {
  93.       TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 0<<CS11 | 1<<CS10; //高频模式,分频器1
  94.       mode = 1;
  95.     }
  96.     if(frq>80000){
  97.       frq = 80000;
  98.       tone(11,600,50);  //最高80KHz,超出量程播放提示音
  99.     }
  100.     temp = 31250/frq*(1+255*mode);
  101.     ICR1 = int(temp);
  102.     TCNT1=0;
  103.     lcd.setCursor(5,0);
  104.     lcd.print(frq);
  105.     lcd.print("      ");
  106.     delay(1);
  107.   }
  108.   if(isChanged(1))//判断为逆时针旋转编码器
  109.   {
  110.     frq -= STEP;
  111.     if(frq<500 && mode==1)//需要改为低频模式的情况
  112.     {
  113.       TCCR1B = 1<<WGM13 | 1<<WGM12 | 1<<CS12 | 0<<CS11 | 0<<CS10;   //低频模式,分频器256
  114.       mode = 0;
  115.     }
  116.     if(frq<1){
  117.       frq = 1;
  118.       tone(11,600,50);//频率最低1Hz,超出时发出滴的声音
  119.     }
  120.     temp = 31250/frq*(1+255*mode);
  121.     ICR1 = int(temp);
  122.     TCNT1=0;
  123.     lcd.setCursor(5,0);
  124.     lcd.print(frq);
  125.     lcd.print("       ");
  126.     delay(1);
  127.   }
  128.   //判断按键是否按下
  129.   if(!digitalRead(SW)){
  130.     delay(140);
  131.     if(!digitalRead(SW)){
  132.       STEP*=10;
  133.       if(STEP>1000)
  134.         STEP=0.1;
  135.     }
  136.     lcd.setCursor(5,1);
  137.     lcd.print(STEP);
  138.     lcd.print("      ");
  139.   }
  140. }

  141. //判断iPin脚电平是否变化,是返回1,否则返回0
  142. bool isChanged(int iPin){
  143.   bool newState = digitalRead(PIN[iPin]);
  144.   if(newState!=oldState[iPin]){
  145.     oldState[0]=newState;
  146.     oldState[1]=newState;
  147.     return 1;
  148.   }
  149.   else
  150.     return 0;
  151. }

  152. void initInterrupt(){
  153.   TCCR1A = 0;     //普通模式
  154.   TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 0<<CS11 | 1<<CS10; //CTC模式:ICR1触发,初始分频:cpu主频16MHz
  155.   ICR1 = int(8000000/frq);         //寄存器,计数器达到该值时产生中断信号
  156.   TIMSK1 |= 1<<ICIE1;   //允许捕捉事件中断
  157. }

  158. //中断函数
  159. ISR(TIMER1_CAPT_vect){
  160.   TP = ~TP;
  161.   PORTC = TP;
  162. }
复制代码



代码合二为一后串口监视器和绘图器截图。怎样才能让它正常、真正合二为一呢?


1.png 2.png 3.png







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

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 02:47 , Processed in 0.101307 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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