使用avrdude让Atmega16A启用外部晶振

Atmega16A出厂默认配置的融丝位让其使用内部RC震荡电路,对于温度敏感的场合(比如超声波测距),自带的RC震荡电路的误差就会变大,因此有必要使用外部晶振。
通过在网上搜索到的资料,这里记录下我现在的做法,方便以后回忆。

首先焊好最小系统后,连接上ISP,然后在命令行下进入avrdude的shell模式:

[lexchou@localhost avr-test]$ sudo avrdude -P usb -pm16 -c usbasp -t

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9403
avrdude> 

命令part可以得到当前MCU的详细信息,这里我的Atmega16A的结果:

avrdude> part
>>> part 

AVR Part                      : ATMEGA16
Chip Erase delay              : 9000 us
PAGEL                         : PD7
BS2                           : PA0
RESET disposition             : dedicated
RETRY pulse                   : SCK
serial program mode           : yes
parallel program mode         : yes
Timeout                       : 200
StabDelay                     : 100
CmdexeDelay                   : 25
SyncLoops                     : 32
ByteDelay                     : 0
PollIndex                     : 3
PollValue                     : 0x53
Memory Detail                 :

                         Block Poll               Page                       Polled
  Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
  ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
  eeprom         4    10   128    0 no        512    4      0  9000  9000 0xff 0xff
  flash         33     6   128    0 yes     16384  128    128  4500  4500 0xff 0xff
  lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
  lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
  hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
  signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
  calibration    0     0     0    0 no          4    0      0     0     0 0x00 0x00

其中hfuse和lfuse分别为融丝位的高字节和低字节,具体的定义为:

<td>
  位号
</td>

<td>
  描述
</td>

<td>
  默认值
</td>
<td>
  7
</td>

<td>
  使能 OCD
</td>

<td>
  1 ( 未编程, OCD 禁用 )
</td>
<td>
  6
</td>

<td>
  使能 JTAG
</td>

<td>
  0 ( 编程, JTAG 使能 )
</td>
<td>
  5
</td>

<td>
  使能串行程序和数据下载
</td>

<td>
  0 ( 被编程, SPI 编程使能 )
</td>
<td>
  4
</td>

<td>
  振荡器选项
</td>

<td>
  1 ( 未编程 )
</td>
<td>
  3
</td>

<td>
  执行芯片擦除时 EEPROM 的内
</td>

<td>
  1 ( 未被编程 ),EEPROM 内容不保留
</td>
<td>
  2
</td>

<td>
  选择 Boot 区大小
</td>

<td>
  0 ( 被编程 )
</td>
<td>
  1
</td>

<td>
  选择 Boot 区大小
</td>

<td>
  0 ( 被编程 )
</td>
<td>
  0
</td>

<td>
  选择复位向量
</td>

<td>
  1 ( 未被编程 )
</td>
<td>
  位号
</td>

<td>
  描述
</td>

<td>
  默认值
</td>
<td>
  7
</td>

<td>
  BOD 触发电平
</td>

<td>
  1 ( 未被编程 )
</td>
<td>
  6
</td>

<td>
  BOD 使能
</td>

<td>
  1 ( 未被编程, BOD 禁用 )
</td>
<td>
  5
</td>

<td>
  选择启动时间
</td>

<td>
  1 ( 未被编程 )
</td>
<td>
  4
</td>

<td>
  选择启动时间
</td>

<td>
  0 ( 被编程 )
</td>
<td>
  3
</td>

<td>
  选择时钟源
</td>

<td>
  0 ( 被编程 )
</td>
<td>
  2
</td>

<td>
  选择时钟源
</td>

<td>
  0 ( 被编程 )
</td>
<td>
  1
</td>

<td>
  选择时钟源
</td>

<td>
  0 ( 被编程 )
</td>
<td>
</td>

<td>
  选择时钟源
</td>

<td>
  1 ( 未被编程 )
</td>

要配置使用外部晶振,就得改lfuse的CKSEL0~CKSEL3了,文档中这么定义的:

<td>
  CKSEL3..0
</td>
<td>
  1111 &#8211; 1010
</td>
<td>
  1001
</td>
<td>
  1000 &#8211; 0101
</td>
<td>
  0100 &#8211; 0001
</td>
<td>
  0000
</td>

看看这个新的MCU的lfuse值是多少:

avrdude> d lfuse
>>> d lfuse 
0000  e1                                                |.               |

为了让MCU使用外部晶振,需要将低4位设置为1111,使用w命令:

avrdude> w lfuse 0 0xef
>>> w lfuse 0 0xef 

然后就可以用了。


Last modified on 2013-06-06