极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 17328|回复: 6

8F328P-U 的 PWM 訊號產生器

[复制链接]
发表于 2018-9-11 10:45:58 | 显示全部楼层 |阅读模式
  1. 頻率範圍:250Hz ~ 150kHz (改動 operatingFrequency 值)
  2. * 註:若更改 clockFrequency 值 為 32,頻率可提高至 300kHz

  3. 佔空比: 0% ~ 100% (改動 dutycycle 值)

  4. =======================================
  5. //PWM_generator

  6. #define PWMoutput 9
  7. #define clockFrequencyMHz 16
  8. #define operatingFrequency 150000

  9. byte dutyCycle = 50;
  10. unsigned int dutyCycleAdjusted = 40;

  11. void setup() {
  12.   setInternalClock(clockFrequencyMHz);

  13.   pinMode(PWMoutput, OUTPUT); //D9
  14.   Serial.begin(115200);

  15.   setupPWM16();
  16.   dutyCycleAdjusted = map(dutyCycle, 0, 100, 0, ICR1);
  17.   analogWrite16(PWMoutput, dutyCycleAdjusted);
  18. }

  19. void loop() {
  20.   checkSerialSetDutyCycle();
  21. }

  22. void setInternalClock(byte clock) {
  23.   sysClock(INT_OSC); //use internal 32MHz RC clock
  24.   CLKPR = 0x80;
  25.   switch (clock) {
  26.     case 32: CLKPR = 0x00;   //Divider=1, =>32MHz/1 = 32MHz
  27.       break;
  28.     case 16: CLKPR = 0x01;   //Divider=2, =>32MHz/2 = 16MHz
  29.       break;
  30.   }
  31. }

  32. void setupPWM16() {
  33.   DDRB |= _BV(PB1) | _BV(PB2);        /* set pins as outputs */
  34.   TCCR1A = _BV(COM1A1) | _BV(COM1B1)  /* non-inverting PWM */
  35.            | _BV(WGM11);                   /* mode 14: fast PWM, TOP=ICR1 */
  36.   TCCR1B = _BV(WGM13) | _BV(WGM12)
  37.            | _BV(CS10);                    /* no prescaler */
  38.   ICR1 = ((clockFrequencyMHz * 1000000) / operatingFrequency)-1;   /* TOP counter value (freeing OCR1A*/
  39. //  ICR1 = 16;   /* TOP counter value (freeing OCR1A*/
  40. }
  41. /* Comments about the setup
  42.   Changing ICR1 will effect the amount of bits of resolution.
  43.   ICR1 = 0xffff; (65535) 16-bit resolution
  44.   ICR1 = 0x7FFF; (32767) 15-bit resolution
  45.   ICR1 = 0x3FFF; (16383) 14-bit resolution etc....

  46.   Changing the prescaler will effect the frequency of the PWM signal.
  47.   Frequency[Hz}=CPU/(ICR1+1) where in this case CPU=16 MHz
  48.   16-bit PWM will be>>> 16000000/(65535+1)=244,14Hz
  49. */

  50. /* 16-bit version of analogWrite(). Works only on pins 9 and 10. */
  51. void analogWrite16(uint8_t pin, uint16_t val)
  52. {
  53.   switch (pin) {
  54.     case  9: OCR1A = val; break;
  55.     case 10: OCR1B = val; break;
  56.   }
  57. }

  58. void checkSerialSetDutyCycle() {
  59.   // check if data has been sent from the computer:
  60.   if (Serial.available()) {
  61.     // read the most recent byte (which will be from 0 to 255):
  62.     dutyCycle = Serial.read();
  63.     // set the brightness of the LED:
  64.     if (dutyCycle == 0) {
  65.       dutyCycleAdjusted = 0;
  66.       digitalWrite(PWMoutput, LOW);
  67.     }
  68.     else {
  69.       setupPWM16();
  70.       dutyCycleAdjusted = map(dutyCycle, 0, 100, 0, ICR1);
  71.       analogWrite16(PWMoutput, dutyCycleAdjusted);
  72.     }
  73.   }
  74. }


  75. /* ================================================
  76. // Processing control program

  77.   import processing.serial.*;
  78.   Serial port;

  79.   void setup() {
  80.     size(201, 150);

  81.     println("Available serial ports:");
  82.     // if using Processing 2.1 or later, use Serial.printArray()
  83.     println(Serial.list());

  84.     // Uses the first port in this list (number 0). Change this to select the port
  85.     // corresponding to your Arduino board. The last parameter (e.g. 9600) is the
  86.     // speed of the communication. It has to correspond to the value passed to
  87.     // Serial.begin() in your Arduino sketch.
  88.     port = new Serial(this, Serial.list()[1], 115200);

  89.     // If you know the name of the port used by the Arduino board, you can specify
  90.     // it directly like this.
  91.     //port = new Serial(this, "COM1", 9600);
  92.   }

  93.   void draw() {
  94.     // draw a gradient from black to white
  95.     for (int i = 0; i < 200; i++) {
  96.       stroke(i);
  97.       line(i, 0, i, 150);
  98.     }

  99.     // write the current X-position of the mouse to the serial port as
  100.     // a single byte
  101.     port.write(mouseX/2);
  102.   //    port.write(0);
  103.   }
  104. */
复制代码
回复

使用道具 举报

发表于 2018-9-11 11:11:23 | 显示全部楼层
这样子会和其他函数冲突不
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-11 11:31:56 | 显示全部楼层
Timer1:
Timer1 is a 16bit timer.
In the Arduino world the Servo library uses timer1 on Arduino Uno (timer5 on Arduino Mega).

跟 Timer1 有關的會有影響。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-11 11:36:43 | 显示全部楼层
這個主要是用來測試 LGT8F328P的能力,能上到300kHz PWM 的單片機,比市面一般的 8-bit單片機算是優勝的了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-11 11:42:04 | 显示全部楼层
在 Arduino 的支援下,編程的門檻也低,配合了processing 的上位機介面,用很低的價錢,就可以學到和得到很有效的學習工具。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-11 12:04:45 | 显示全部楼层
若可接受低的 dutyCycle,工作頻率可以提高到 4MHz (32MHz時鐘,可以到8MHz)。
以下是4MHz時的波形:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2021-1-31 09:18:25 | 显示全部楼层
學習了,剛開始使用這塊U
謝謝。
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 08:53 , Processed in 0.046637 second(s), 20 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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