求教:arduino自带的串口绘图器显示调制的波形

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

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

以下是完整代码

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

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

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

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

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

void setup() {
  Serial.begin(9600);       //定义Arduino 串口输出
  initInterrupt();          //初始化中断设置
  DDRC = 0xFF;              //将A0~A7均设为输出模式
  pinMode(SW,INPUT_PULLUP);
  pinMode(PIN[0],INPUT_PULLUP);
  pinMode(PIN[1],INPUT_PULLUP);
  oldState[0]=digitalRead(PIN[0]);
  oldState[1]=digitalRead(PIN[1]);
  lcd.begin(16,2);
  lcd.print("Freq:");
  lcd.print(frq);
  lcd.setCursor(0,1);
  lcd.print("Step:");
  lcd.print(STEP);
  
}

void loop() {
  Serial.println(frq); //波形量程输出至串口绘图器
  if(isChanged(0))//判断为顺时针旋转时
  {
    frq +=STEP;
    if(frq>=500 && mode==0)//需要更改分频模式的情况
    {
      TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 0<<CS11 | 1<<CS10; //高频模式,分频器1
      mode = 1;
    }
    if(frq>80000){
      frq = 80000;
      tone(11,600,50);  //最高80KHz,超出量程播放提示音
    }
    temp = 31250/frq*(1+255*mode);
    ICR1 = int(temp);
    TCNT1=0;
    lcd.setCursor(5,0);
    lcd.print(frq);
    lcd.print("      ");
    delay(1);
  }
  if(isChanged(1))//判断为逆时针旋转编码器
  {
    frq -= STEP;
    if(frq<500 && mode==1)//需要改为低频模式的情况
    {
      TCCR1B = 1<<WGM13 | 1<<WGM12 | 1<<CS12 | 0<<CS11 | 0<<CS10;   //低频模式,分频器256
      mode = 0;
    }
    if(frq<1){
      frq = 1;
      tone(11,600,50);//频率最低1Hz,超出时发出滴的声音
    }
    temp = 31250/frq*(1+255*mode);
    ICR1 = int(temp);
    TCNT1=0;
    lcd.setCursor(5,0);
    lcd.print(frq);
    lcd.print("       ");
    delay(1);
  }
  //判断按键是否按下
  if(!digitalRead(SW)){
    delay(140);
    if(!digitalRead(SW)){
      STEP*=10;
      if(STEP>1000)
        STEP=0.1;
    }
    lcd.setCursor(5,1);
    lcd.print(STEP);
    lcd.print("      ");
  }
}

//判断iPin脚电平是否变化,是返回1,否则返回0
bool isChanged(int iPin){   
  bool newState = digitalRead(PIN[iPin]);
  if(newState!=oldState[iPin]){
    oldState[0]=newState;
    oldState[1]=newState;
    return 1;
  }
  else
    return 0;
}

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

//中断函数
ISR(TIMER1_CAPT_vect){
  TP = ~TP;
  PORTC = TP;
}

参考代码:

float x=0;
float y=0;
const float pi=3.14;
int z=0;
float v=0;
int w=0;
boolean OK=true;
void setup() {
Serial.begin(9600);
}
// the loop function runs over and over again forever
void loop() {
if (w==0){
v=x*pi/180; // making deg in radians
y=sin(v); //calculate sinus
z=y*250; // calculate duty cycle(250 not 255 because will help to turn off transistors)
delay(100);
if(OK==true){
x=x+0.689;// increase the angle
}
}
if (x>90){
OK=false;
}
if (OK==false){
x=x-0.689; //decreasing the angle for the other half
}
Serial.println(z);// on the serial monitor will appear duty cycles between 0 and 180 deg
}

代码整合以后:

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

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

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

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

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

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

void setup() {
  Serial.begin(9600);       //定义Arduino 串口输出波特率
  initInterrupt();          //初始化中断设置
  DDRC = 0xFF;              //将A0~A7均设为输出模式
  pinMode(SW,INPUT_PULLUP);
  pinMode(PIN[0],INPUT_PULLUP);
  pinMode(PIN[1],INPUT_PULLUP);
  oldState[0]=digitalRead(PIN[0]);
  oldState[1]=digitalRead(PIN[1]);
  lcd.begin(16,2);
  lcd.print("Freq:");
  lcd.print(frq);
  lcd.setCursor(0,1);
  lcd.print("Step:");
  lcd.print(STEP);
  
}

void loop() {

<b>//绘图器相关-Add</b>
<font color="#9932cc">{
if (w==0){
v=x*pi/180; // making deg in radians
y=sin(v); //calculate sinus
z=y*250; // calculate duty cycle(250 not 255 because will help to turn off transistors)
delay(100);
if(OK==true){
x=x+0.689;// increase the angle
}
}
if (x>90){
OK=false;
}
if (OK==false){
x=x-0.689; //decreasing the angle for the other half
}
 Serial.println(z,frq); //波形量程输出至串口绘图器
}</font>
//原代码
   if(isChanged(0))//判断为顺时针旋转时
  {
    frq +=STEP;
    if(frq>=500 && mode==0)//需要更改分频模式的情况
    {
      TCCR1B = 1<<WGM13 | 1<<WGM12 | 0<<CS12 | 0<<CS11 | 1<<CS10; //高频模式,分频器1
      mode = 1;
    }
    if(frq>80000){
      frq = 80000;
      tone(11,600,50);  //最高80KHz,超出量程播放提示音
    }
    temp = 31250/frq*(1+255*mode);
    ICR1 = int(temp);
    TCNT1=0;
    lcd.setCursor(5,0);
    lcd.print(frq);
    lcd.print("      ");
    delay(1);
  }
  if(isChanged(1))//判断为逆时针旋转编码器
  {
    frq -= STEP;
    if(frq<500 && mode==1)//需要改为低频模式的情况
    {
      TCCR1B = 1<<WGM13 | 1<<WGM12 | 1<<CS12 | 0<<CS11 | 0<<CS10;   //低频模式,分频器256
      mode = 0;
    }
    if(frq<1){
      frq = 1;
      tone(11,600,50);//频率最低1Hz,超出时发出滴的声音
    }
    temp = 31250/frq*(1+255*mode);
    ICR1 = int(temp);
    TCNT1=0;
    lcd.setCursor(5,0);
    lcd.print(frq);
    lcd.print("       ");
    delay(1);
  }
  //判断按键是否按下
  if(!digitalRead(SW)){
    delay(140);
    if(!digitalRead(SW)){
      STEP*=10;
      if(STEP>1000)
        STEP=0.1;
    }
    lcd.setCursor(5,1);
    lcd.print(STEP);
    lcd.print("      ");
  }
}

//判断iPin脚电平是否变化,是返回1,否则返回0
bool isChanged(int iPin){
  bool newState = digitalRead(PIN[iPin]);
  if(newState!=oldState[iPin]){
    oldState[0]=newState;
    oldState[1]=newState;
    return 1;
  }
  else
    return 0;
}

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

//中断函数
ISR(TIMER1_CAPT_vect){
  TP = ~TP;
  PORTC = TP;
}

输出的频率用示波器测试正常,只是Arduino串口监视器和绘图器的不正常。
请赐教

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.