上传带注释的iom32v.h和iom8v.h头文件,希望对大家有用,编程的时候不用查数据手册

点击此处下载 ourdev_283682.rar(文件大小:13K) (原文件名:avr头文件.rar) 
包括iom8v.h,iom32v.h
#ifndef __iom32v_h
#define __iom32v_h

/*typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;      // Unsigned  8 bit quantity
typedef signed   char  INT8S;      // Signed    8 bit quantity
typedef unsigned int   INT16U;     // Unsigned 16 bit quantity
typedef signed   int   INT16S;     // Signed   16 bit quantity
typedef unsigned long  INT32U;     // Unsigned 32 bit quantity
typedef signed   long  INT32S;     // Signed   32 bit quantity
typedef float          FP32;       // Single precision floating point

//位定义(m.b.b0=1;)整体定义m.a=0xff;同时使用联合和结构
union
{ struct
  { unsigned b0:1;
   unsigned b1:1;
   unsigned b2:1;
   unsigned b3:1;
   unsigned b4:1;
   unsigned b5:1;
   unsigned b6:1;
   unsigned b7:1;
  }b;
  INT8U a;
}m;

for(i=n;n!=0;n--);    //延时周期 4n   (i定义为unsigned char)
for(i=n;n!=0;n--);    //延时周期 6n+1 (i定义为unsigned int)

unsigned char  1 0~255
signed char    1 -128~127
char(*)        1 0~255
unsigned short 2 0~65535
signed short   2 -32768~32767
unsigned int   2 0~65535
signed int     2 -32768~32767
unsigned long  4 0~4294967295
signed long    4 -2147483648~2147483647
float      4
double     4
*/
/*ATmega32所有的I/O及外设都被放置于I/O空间。所有的I/O位置都可以通过IN 与OUT指令
来访问,在32个通用工作寄存器和I/O 之间传输数据。 地址为0x00 - 0x1F 的I/O 寄存器
还可用SBI 和CBI 指令直接进行位寻址,而SBIS 和SBIC 则用来检查某一位的值。更多
内容请参见指令集。使用IN 和OUT指令时地址必须在 0x00 - 0x3F之间。如果要象SRAM
一样通过LD 和ST 指令访问I/O 寄存器,相应的地址要加上0x20。*/

/* ATmega32 header file for
   ImageCraft ICCAVR compiler*/
/* not strictly sorted by address no more */
/* interrupt vector number definitions added */
/* last changed 2002/05/01 */

/* 2 wire serial interface 400kHz 两线串行接口TWI,总线电容要低于400pF*/
#define TWBR (*(volatile unsigned char *)0x20) //比特率寄存器
//TWI 工作在主机模式时,TWBR 值应该不小于10
#define TWSR (*(volatile unsigned char *)0x21) //状态寄存器
#define  TWPS1    1 //预分频位
#define  TWPS0    0
//SCL_Hz=CPU_Hz/(16+2(TWBR)*4^twps指)
//00->1 01->4 10->16 11->64 
#define TWCR (*(volatile unsigned char *)0x56) //控制寄存器
#define  TWINT    7 //中断标志,清零必须通过软件写"1”
#define  TWEA     6 //使能应答,TWEA 清零可以使器件暂时脱离总线。置位后器件重新恢复地址识别。
#define  TWSTA    5 //START 状态标志,发送START之后软件必须清零TWSTA
#define  TWSTO    4 //STOP 状态位,自动清零
#define  TWWC     3 //写冲突标志
#define  TWEN     2 //TWI使能
#define  TWIE     0 //中断使能
#define TWAR (*(volatile unsigned char *)0x22) //地址寄存器
#define  TWGCE    0 //1 读  0写
//高7位为从机地址,
#define TWDR (*(volatile unsigned char *)0x23) //数据寄存器
//只要TWINT 置位,TWDR 的数据就是稳定的,其内容为要发送的下一个字节,或是接收到的数据

/* ADC 50k-200kHz*/
#define ADC  (*(volatile unsigned int *)0x24)  //ADC结果寄存器
#define ADCL (*(volatile unsigned char *)0x24)
#define ADCH (*(volatile unsigned char *)0x25)
#define ADCSR (*(volatile unsigned char *)0x26)
#define ADCSRA (*(volatile unsigned char *)0x26) /*ADC 控制和状态寄存器*/
#define  ADEN     7 /*ADEN置位即启动ADC,否则ADC功能关闭。在转换过程中关闭ADC将立即终止转换。*/
#define  ADSC     6 /*ADC 开始转换*/
#define  ADFR     5 /*1 连续转换选择*/
#define  ADATE    5 /*ADC 自动触发使能*/
#define  ADIF     4 /*在ADC 转换结束,且数据寄存器被更新后, ADIF 置位*/
#define  ADIE     3 /*ADC 中断使能*/
#define  ADPS2    2
#define  ADPS1    1
#define  ADPS0    0
/*分频因子000 001 010 011 100 101 110 111
            2   2   4   8  16  32  64 128*/
#define ADMUX (*(volatile unsigned char *)0x27)/*ADC 多工选择寄存器*/
#define  REFS1    7
#define  REFS0    6
/*00 外部aref 内部VREF关闭 01 AVCC AREF外加滤波电容 10 保留 11 2.56V片内基准电源*/
#define  ADLAR    5  /*0 右对齐 ,1 左对齐*/
#define  MUX3     3
#define  MUX2     2
#define  MUX1     1
#define  MUX0     0
/*通道 0000 0001 0010 0011 0100 0101 0110 0111 1000-1101 1110 1111
          0    1    2    3    4    5    6    7    保留   1.23v 0v*/

/* Analog Comparator */
#define  ACSR (*(volatile unsigned char *)0x28) /*模拟比较器控制和状态寄存器*/
#define  ACD      7 /*ACD 置位时,模拟比较器的电源被切断*/
#define  ACBG     6 /*ACBG 置位后,模拟比较器的正极输入由能隙基准源所取代*/
#define  ACO      5 /*模拟比较器输出*/
#define  ACI      4 /*当比较器的输出事件触发了由ACIS1及ACIS0定义的中断模式时,ACI 置位*/
#define  ACIE     3 /*模拟比较器中断使能*/
#define  ACIC     2 /*ACIC置位后允许通过模拟比较器来触发T/C1 的输入捕捉功能*/
#define  ACIS1    1
#define  ACIS0    0
/*00 输出变化中断 01 保留 10 下降沿中断 11 上升沿中断*/

/* USART */
#define UBRRHI (*(volatile unsigned char *)0x40)
#define UBRRH (*(volatile unsigned char *)0x40) /*波特率寄存器 4位*/
#define  URSEL    7 /*UCSRC与UBRRH选择 0为UBRRH*/
#define UBRR (*(volatile unsigned char *)0x29)
#define UBRRL (*(volatile unsigned char *)0x29) /*波特率寄存器 8位*/
#define UCSRC (*(volatile unsigned char *)0x40) /*控制和状态寄存器C*/
#define  URSEL    7 /*UCSRC与UBRRH选择 1为UCSRC*/
#define  UMSEL    6 /*模式选择 0异步 1同步*/
#define  UPM1     5 /*奇偶校验模式*/
#define  UPM0     4
/*00 禁止 01 保留 10 偶检验 11 奇检验*/
#define  USBS     3 /*停止位选择 0 1位 1 2位*/
#define  UCSZ1    2 /*字符长度与UCSRB中的UCSZ2共用*/
#define  UCSZ0    1
/*000 5位 001 6位 010 7位 011 8位 100 101 110 保留 111 9位*/
#define  UCPOL    0 /*时钟极性 这一位仅用于同步工作模式*/

#define UCSRB (*(volatile unsigned char *)0x2A) /*控制和状态寄存器B*/
#define  RXCIE    7  /*接收结束中断使能*/
#define  TXCIE    6  /*发送结束中断使能*/
#define  UDRIE    5  /*数据寄存器空中断使能*/
#define  RXEN     4  /*置位后将启动USART 接收器*/
#define  TXEN     3  /*置位后将启动USART 发送器*/
#define  UCSZ2    2  /*字符长度*/
#define  RXB8     1  /*接收数据位8*/
#define  TXB8     0  /*发送数据位8*/
#define UCSRA (*(volatile unsigned char *)0x2B) /*控制和状态寄存器A*/
#define  RXC      7 /*接收缓冲器中有未读出的数据时RXC 置位,否则清零*/
#define  TXC      6 /*发送移位缓冲器中的数据被送出,且当发送缓冲器 (UDR) 为空时TXC 置位,自动清零和写1清零*/
#define  UDRE     5 /*UDRE为1说明发送缓冲器为空,已准备好进行数据接收。*/
#define  FE       4 /*帧错误*/
#define  DOR      3 /*数据溢出时DOR 置位*/
#define  OVR      3 /*This definition differs from the databook*/
#define  PE       2 /*奇偶校验错误*/
#define  U2X      1 /*倍速发送,异步有用*/
#define  MPCM     0 /*多处理器通信模式*/
#define UDR (*(volatile unsigned char *)0x2C)
/*发送和接收数据寄存器 相当于51的SBUF*/

/* SPI */
#define SPCR (*(volatile unsigned char *)0x2D)
#define  SPIE     7  //中断使能
#define  SPE      6  //使能SPI
#define  DORD     5  //数据次序,'1' 低位先发送
#define  MSTR     4  //主从机选择 '1'为主机
#define  CPOL     3  //CPOL置位表示空闲时SCK 为高电平
#define  CPHA     2  //时钟相位,'0'CPHA 决定数据是在SCK 的起始沿采样
#define  SPR1     1  //SPI 时钟速率选择1 与0
#define  SPR0     0
/*00 1/4    01 1/16   10 1/64   11 1/128*/
#define SPSR (*(volatile unsigned char *)0x2E)
#define  SPIF     7  //中断标志
#define  WCOL     6  //写冲突标志,在发送当中对SPI 数据寄存器SPDR写数据将置位WCOL。
//WCOL可以通过先读SPSR,紧接着访问SPDR 来清零。
#define  SPI2X    0  //置位后SPI 的速度加倍
#define SPDR (*(volatile unsigned char *)0x2F) //SPI 数据寄存器
/*CPOL 与CPHA 功能
                       起始沿          结束沿    SPI 模式
CPOL = 0, CPHA = 0 采样 ( 上升沿) 设置 ( 下降沿) 0
CPOL = 0, CPHA = 1 设置 ( 上升沿) 采样 ( 下降沿) 1
CPOL = 1, CPHA = 0 采样 ( 下降沿) 设置 ( 上升沿) 2
CPOL = 1, CPHA = 1 设置 ( 下降沿) 采样 ( 上升沿) 3
SPI 引脚重载(1)
引脚方向, SPI 主机方向, SPI 从机
MOSI     用户定义   输入
MISO     输入   用户定义
SCK     用户定义   输入
SS     用户定义   输入*/

/*void SPI_MasterInit(void)
{
    //设置MOSI,SCK,SS为输出,MISO为输入 
DDR_SPI |=(1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
// 使能SPI 主机模式,设置时钟速率为fck/16 
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR0);
//使能SPI,主机模式,SCK空闲时为高,SCK结束沿采样,1/16
}
void SPI_SlaveInit(void)
{
    //设置MISO为输出,其他为输入
   DDR_SPI |= (1<<DD_MISO);
   // 使能 SPI
   SPCR = (1<<SPE)|(1<<CPOL)|(1<<CPHA)|(1<<SPR0);
}
*/
/* Port D */
#define PIND (*(volatile unsigned char *)0x30)
#define DDRD (*(volatile unsigned char *)0x31)
#define PORTD (*(volatile unsigned char *)0x32)

/* Port C */
#define PINC (*(volatile unsigned char *)0x33)
#define DDRC (*(volatile unsigned char *)0x34)
#define PORTC (*(volatile unsigned char *)0x35)

/* Port B */
#define PINB (*(volatile unsigned char *)0x36)
/*端口B 输入引脚地址*/
#define DDRB (*(volatile unsigned char *)0x37)
/*端口B 数据方向寄存器 1 为输出 0 为输入*/
#define PORTB (*(volatile unsigned char *)0x38)
/*端口B 数据寄存器*/
 
/* Port A */
#define PINA (*(volatile unsigned char *)0x39)
#define DDRA (*(volatile unsigned char *)0x3A)
#define PORTA (*(volatile unsigned char *)0x3B)

/*未用脚,用内部上拉,或者外部上下拉
先PROTA=0xff;后DDRA=0x00;
引脚配置为输入时,若PORTxn 为"1“,上拉电阻将使能。
当引脚配置为输出时,若PORTxn 为"1“,引脚输出高电平("1“),
在上拉输入和输出低电平之间切换也有同样的问题。用户必须选择高阻态({DDxn,
PORTxn} = 0b00) 或输出高电平({DDxn, PORTxn} = 0b11) 作为中间步骤。
DDxn PORTxn PUD(SFIOR中) I/O  上拉电阻 说明
0   0  X   输入 No     高阻态 (Hi-Z)
0   1  0   输入 Yes     被外部电路拉低时将输出电流
0   1  1   输入 No     高阻态(Hi-Z)
1   0  X   输出 No     输出低电平 ( 漏电流)
1   1  X   输出 No     输出高电平 ( 源电流)*/

/* EEPROM */
#define EECR (*(volatile unsigned char *)0x3C) //控制寄存器
#define  EERIE    3  //就绪中断使能
#define  EEMWE    2  //主机写使能,EEWE置位是否可以启动EEPROM写操作
#define  EEWE     1  //写使能,置位EEWE以便将数据写入EEPROM
#define  EERE     0  //EEPROM 读使能
/* 写时序如下( 第3 步和第4 步的次序并不重要):
1. 等待EEWE 位变为零。
2. 等待SPMCSR 中的SPMEN 位变为零。
3. 将新的EEPROM 地址写入EEAR( 可选)。
4. 将新的EEPROM 数据写入EEDR( 可选)。
5. 对EECR 寄存器的EEMWE 写"1",同时清零EEWE。
6. 在置位EEMWE 的4 个周期内,置位EEWE*/
#define EEDR (*(volatile unsigned char *)0x3D) //数据寄存器
#define EEAR (*(volatile unsigned int *)0x3E)
#define EEARL (*(volatile unsigned char *)0x3E) //地址寄存器
#define EEARH (*(volatile unsigned char *)0x3F)

/* Watchdog Timer Control Register */
#define WDTCR (*(volatile unsigned char *)0x41) //看门狗定时器控制寄存器
#define  WDCE     4 //看门狗修改使能,清零WDE 时必须先置位WDCE,否则不能禁止看门狗。
#define  WDTOE    4    /*This definition differs from the databook*/
#define  WDE      3 //看门狗使能,只有在WDCE为"1“时WDE才能清零
/*以下为关闭看门狗的步骤:
1. 在同一个指令内对WDCE 和WDE 写"1“,即使WDE 已经为"1“。
2. 在紧接的4 个时钟周期之内对WDE 写"0”。
asm("cli");WDTCR|=(1<<WDCE)|(1<<WDTOE);WDTCR&=~(1<<WDCE);asm("sei");*/
#define  WDP2     2 //看门狗定时器预分频器2, 1, 和0
#define  WDP1     1
#define  WDP0     0
#define WDT()     (WDTCR = (1<<WDCE) | (1<<WDE)); //启动看门狗
/*清除asm("wdr")
          溢出周期         3V时间  5V时间
   000 16K (16,384)       17.1 ms 16.3 ms
   001 32K (32,768)       34.3 ms 32.5 ms
   010 64K (65,536)       68.5 ms 65 ms
   011 128K (131,072)     0.14 s 0.13 s
   100 256K (262,144)     0.27 s 0.26 s
   101 512K (524,288)     0.55 s 0.52 s
   110 1,024K (1,048,576) 1.1 s 1.0 s
   111 2,048K (2,097,152) 2.2 s 2.1 s*/
/* Timer/Counter 2 */
#define ASSR (*(volatile unsigned char *)0x42) //异步状态寄存器
#define  AS2      3 //异步 T/C2  0-内部 1-TOSC1 时钟
#define  TCN2UB   2 //T/C2 更新中
#define  OCR2UB   1 //输出比较寄存器2 更新中
#define  TCR2UB   0 //T/C2 控制寄存器更新中
#define OCR2 (*(volatile unsigned char *)0x43) //输出比较寄存器2
#define TCNT2 (*(volatile unsigned char *)0x44) //定时器/ 计数器2寄存器
#define TCCR2 (*(volatile unsigned char *)0x45) //T/C2控制寄存器
#define  FOC2     7 //强制输出比较
#define  WGM20    6 //波形产生模式
#define  COM21    5 //比较匹配输出模式
#define  COM20    4
/*com21 com20 
比较输出模式,非PWM 模式
00 正常的端口操作,OC2未连接   01 比较匹配发生时OC2 取反
10 比较匹配发生时OC2清零   11 比较匹配发生时OC2 置位

比较输出模式,快速PWM 模式
00 正常的端口操作,OC2 未连接   01 保留
10 比较匹配发生时OC2 清零 ,计数到TOP 时OC0 置位
11 比较匹配发生时OC2 置位 ,计数到TOP 时OC0 清零

比较输出模式,相位修正PWM 模式
00 正常的端口操作, OC2 未连接   01 保留
10 在升序计数时发生比较匹配将清零OC2 ;降序计数时发生比较匹配将置位OC2
11 在升序计数时发生比较匹配将置位OC2 ;降序计数时发生比较匹配将清零OC2
*/
#define  WGM21    3 //波形产生模式
/*WGM21 WGM20  T/C的工作模式  TOP  OCR2的更新时间 TOV2的置位时刻
  0     0      普通   oxff 立即更新   MAX
  0     1      相位修正PWM    0xFF TOP    BOTTOM
  1  0     CTC    OCR2 立即更新   MAX
  1  1     快速 PWM    0xFF TOP    MAX*/
#define  CS22     2 //时钟选择
#define  CS21     1
#define  CS20     0
/*000 无时钟,T/C 不工作 001 clk/T2S   010 1/8    011 1/32
  100 1/64         101 1/128   110 1/256   111 1/1024
*/
/*在某些操作模式下, TOP 值或T/C 的最大值可由OCR1A 寄存器、ICR1 寄存器,或一
些固定数据来定义。在PWM 模式下用OCR1A 作为TOP 值时, OCR1A 寄存器不能用
作PWM 输出。但此时OCR1A 是双向缓冲的, TOP 值可在运行过程中得到改变。当需
要一个固定的TOP 值时可以使用ICR1 寄存器,从而释放OCR1A 来用作PWM 的输出。*/
/* Timer/Counter 1 */
#define ICR1 (*(volatile unsigned int *)0x46)  //输入捕捉寄存器
#define ICR1L (*(volatile unsigned char *)0x46)
#define ICR1H (*(volatile unsigned char *)0x47)
#define OCR1B (*(volatile unsigned int *)0x48)  //输出比较寄存器1B
#define OCR1BL (*(volatile unsigned char *)0x48)
#define OCR1BH (*(volatile unsigned char *)0x49)
#define OCR1A (*(volatile unsigned int *)0x4A)  //输出比较寄存器1A
#define OCR1AL (*(volatile unsigned char *)0x4A)
#define OCR1AH (*(volatile unsigned char *)0x4B)
#define TCNT1 (*(volatile unsigned int *)0x4C)  //定时器/计数器TCNT1
#define TCNT1L (*(volatile unsigned char *)0x4C)
#define TCNT1H (*(volatile unsigned char *)0x4D)
#define TCCR1B (*(volatile unsigned char *)0x4E) //T/C控制寄存器B
#define  ICNC1    7 //输入捕捉噪声抑制器,4个相同才输入
#define  ICES1    6 //输入捕捉触发沿选择 0下降沿  1上升沿
#define  WGM13    4
#define  WGM12    3
#define  CS12     2 //分频
#define  CS11     1
#define  CS10     0
/*CS12:0 = 0 时,计数器停止计数。
  CS12:0 = 1 时,系统内部时钟直接作为T/C的时钟源,
  CS12:0 = 2 8分频 3 64分频 4 256分频 5 1024分频
  CSn2:0 = 6 外部T1 引脚,下降沿驱动
  CSn2:0 = 7 外部T1 引脚,上升沿驱动*/
#define TCCR1A (*(volatile unsigned char *)0x4F)//T/C控制寄存器A
#define  COM1A1   7 //通道A 的比较输出模式
#define  COM1A0   6
#define  COM1B1   5 //通道B 的比较输出模式
#define  COM1B0   4
/*比较输出模式,非PWM
  0 0 普通端口操作,OC1A/OC1B 未连接
  0 1 比较匹配时OC1A/OC1B 电平取反
  1 0 比较匹配时清零OC1A/OC1B( 输出低电平)
  1 1 比较匹配时置位 OC1A/OC1B ( 输出高电平)
  比较输出模式,快速PWM
  0 0 普通端口操作, OC1A/OC1B 未连接
  0 1 WGM13:0 = 15: 比较匹配时OC1A 取反 ,OC1B 未连接。WGM13:0 为其它值时为普通端口操作, OC1A/OC1B 未连接
  1 0 比较匹配时清零 OC1A/OC1B, OC1A/OC1B在TOP 时置位
  1 1 比较匹配时置位 OC1A/OC1B, OC1A/OC1B在TOP 时清零
  比较输出模式,相位修正及相频修正 PWM 模式
  0 0 普通端口操作, OC1A/OC1B 未连接
  0 1 WGM13:0 = 9 或14: 比较匹配时OC1A 取反,OC1B 未连接。 WGM13:0为其它值时为普通端口操作, OC1A/OC1B 未连接
  1 0 升序记数时比较匹配将清零OC1A/OC1B,降序记数时比较匹配将置位OC1A/OC1B
  1 1 升序记数时比较匹配将置位OC1A/OC1B,降序记数时比较匹配将清零OC1A/OC1B*/
#define  FOC1A    3 //通道A 强制输出比较
#define  FOC1B    2 //通道B 强制输出比较
//FOC1A/FOC1B只有当WGM13:0指定为非PWM模式时被激活
#define  WGM11    1
#define  WGM10    0
/* 模式 WGM13:0 定时器/计数器工作模式 TOP   OCR1x更新时刻 TOV1置位时刻
   0 0 0 0 0   普通模式  0xFFFF 立即更新  MAX
   1 0 0 0 1   8位相位修正PWM   0x00FF TOP   BOTTOM
   2 0 0 1 0   9位相位修正PWM   0x01FF TOP   BOTTOM
   3 0 0 1 1   10位相位修正PWM   0x03FF TOP   BOTTOM
   4 0 1 0 0   CTC   OCR1A  立即更新  MAX
   5 0 1 0 1   8位快速PWM   0x00FF TOP   TOP
   6 0 1 1 0   9位快速PWM   0x01FF TOP   TOP
   7 0 1 1 1   10位快速PWM   0x03FF TOP   TOP
   8 1 0 0 0   相位与频率修正PWM   ICR1  BOTTOM   BOTTOM
   9 1 0 0 1   相位与频率修正PWM   OCR1A  BOTTOM   BOTTOM
  10 1 0 1 0   相位修正PWM   ICR1  TOP   BOTTOM
  11 1 0 1 1   相位修正PWM   OCR1A  TOP   BOTTOM
  12 1 1 0 0   CTC   ICR1  立即更新  MAX
  13 1 1 0 1   保留  –  –   –
  14 1 1 1 0   快速PWM   ICR1   TOP   TOP
  15 1 1 1 1   快速PWM   OCR1A  TOP   TOP*/

/* Special Function I/O register */
#define SFIOR (*(volatile unsigned char *)0x50)/*特殊功能IO 寄存器*/
#define  ADTS2    7  //ADC 自动触发源
#define  ADTS1    6
#define  ADTS0    5
/*000 连续转换模式 001 模拟比较器 010 外部中断请求0 011 定时器/计数器0比较匹配
  100 定时器/计数器0溢出 101 定时器/计数器比较匹配B
  110 定时器/计数器1溢出 111 定时器/计数器1捕捉事件*/
#define  ADHSM    4 //保留
#define  ACME     3 //模拟比较器多路复用器使能,逻辑"1,ADC 处于关闭状态
#define  PUD      2 //禁用上拉电阻
#define  PSR2     1 //预分频复位T/C2 写'1'
#define  PSR10    0 //置位时T/C1与T/C0的预分频器复位。由硬件自动清零

/* Oscillator Calibration */
#define OSCCAL (*(volatile unsigned char *)0x51) //振荡器标定寄存器
/* On-Chip Debug register */
#define OCDR (*(volatile unsigned char *)0x51)

/* Timer/Counter 0 */
#define OCR0 (*(volatile unsigned char *)0x5C)
#define TCNT0 (*(volatile unsigned char *)0x52)
/*T/C 寄存器*/
#define TCCR0 (*(volatile unsigned char *)0x53)
/*T/C 控制寄存器*/
#define  FOC0     7  //强制输出比较
#define  WGM00    6  //WGM01:0: 波形产生模式
#define  COM01    5  //COM01:0: 比较匹配输出模式
#define  COM00    4
#define  WGM01    3
#define  CS02     2
#define  CS01     1
#define  CS00     0
/*模式 WGM01 WGM00 T/C 的工作模式  TOP  OCR0更新时间 TOV0置位时刻
  0    0   0     普通    0xFF 立即更新  MAX
  1    0   1     PWM,相位修正   0xFF TOP   BOTTOM
  2    1   0     CTC     OCR0 立即  更新MAX
  3    1   1     快速 PWM     0xFF TOP   MAX*/
  
/*000 无时钟 001 clk/1 ( 没有预分频) 010 clk/8 ( 来自预分频器) 011 clk/64
  100 clk/256 101 clk/1024 110 T0引脚输入,下降沿触发 111 T0引脚输入,上升沿触发*/

/* MCU general */
#define MCUCSR (*(volatile unsigned char *)0x54)
#define MCUSR (*(volatile unsigned char *)0x54) //控制和状态寄存器
#define  JTD      7 //禁止JTAG 接口,必须在四个时钟周期内将期望的数值两次写入JTD。
#define  ISC2     6 //中断2 触发方式控制 0-下降沿,1-上升沿
#define  JTRF     4 //JTAG 复位标志
#define  WDRF     3 //看门狗复位标志,上电复位和写0清零
#define  BORF     2 //掉电检测复位发生时置位,上电复位和写0清零
#define  EXTRF    1 //外部复位标志,上电复位和写0清零
#define  PORF     0 //上电复位标志,只能通过写"0"来清除
#define MCUCR (*(volatile unsigned char *)0x55) //MCU 控制寄存
#define  SE       7 //休眠使能
#define  SM2      6
#define  SM1      5
#define  SM0      4
/*000 空闲模式 001 ADC 噪声抑制模式 010 掉电模式 011 省电模式
  100 保留    101 保留 110 仅在使用外部晶体或谐振器时Standby 模式才可用 */
#define  ISC11    3 //中断1 触发方式控制
#define  ISC10    2
#define  ISC01    1 //中断0 触发方式控制
#define  ISC00    0
/*00 为低电平时产生中断请求 01 引脚上任意的逻辑电平变化都将引发中断
  10 下降沿产生中断请求 11 上升沿产生中断请求*/

/* SPM Conrol Register */
#define SPMCR (*(volatile unsigned char *)0x57) //保存程序存储器控制寄存器
#define  SPMIE    7 //中断使能
#define  RWWSB    6 //RWW 区忙标志
#define  RWWSRE   4 //RWW 区读使能
#define  BLBSET   3 //Boot 锁定位设置
#define  PGWRT    2 //页写入
#define  PGERS    1 //页擦除
#define  SPMEN    0 //存贮程序存储器使能

/* Timer/Counter Interrupts */
#define TIFR (*(volatile unsigned char *)0x58) //定时器/ 计数器 中断标志寄存器
#define  OCF2     7 //输出比较标志2
#define  TOV2     6 //T/C2 溢出标志
#define  ICF1     5 //T/C1 输入捕捉标志
#define  OCF1A    4 //T/C1 输出比较 A 匹配标志
#define  OCF1B    3 //T/C1 输出比较 B 匹配标志
#define  TOV1     2 //T/C1 溢出标志,写1 来清零
#define  OCF0 1 //T/C0 输出比较标志0,中断硬件清零,也可以对其写1 来清零。
#define  TOV0     0 //T/C0 溢出标志,写1 来清零
#define TIMSK (*(volatile unsigned char *)0x59) //定时器/ 计数器中断屏蔽寄存器
#define  OCIE2    7 //T/C2 输出比较匹配中断使能
#define  TOIE2    6 //T/C2 溢出中断使能
#define  TICIE1   5 //T/C1 输入捕捉中断使能
#define  OCIE1A   4 //T/C1 输出比较A匹配中断使能
#define  OCIE1B   3 //T/C1 输出比较B匹配中断使能
#define  TOIE1    2 //T/C1 溢出中断使能
#define  OCIE0 1 //T/C0 输出比较匹配中断使能
#define  TOIE0    0 //T/C0 溢出中断使能

/* General Interrupts */
#define GIFR (*(volatile unsigned char *)0x5A) //通用中断标志寄存器
#define  INTF1    7 //外部中断标志1 ,写入”1” 来清零
#define  INTF0    6 //外部中断标志0 ,写入”1” 来清零
#define  INTF2    5 //外部中断标志2 ,写入”1” 来清零

#define GICR (*(volatile unsigned char *)0x5B) //通用中断控制寄存器
#define  INT1     7 //外部中断请求1 使能
#define  INT0     6 //外部中断请求0 使能
#define  INT2     5 //外部中断请求2 使能
#define  IVSEL    1 //中断向量选择 1时,中断向量转移到Boot 区的起始地址
#define  IVCE     0 //中断向量修改使能,改变IVSEL 时IVCE 必须置位。
/*为了防止无意识地改变中断向量表,修改IVSEL 时需要遵照如下过程:
1. 置位中断向量修改使能位IVCE
2. 在紧接的4 个时钟周期里将需要的数据写入IVSEL,同时对IVCE 写”0”
asm("cli");GICR=1<<IVCE;GICR=1<<IVSEL;asm("sei");*/
/* Stack Pointer */
#define SP (*(volatile unsigned int *)0x5D)
#define SPL (*(volatile unsigned char *)0x5D)
#define SPH (*(volatile unsigned char *)0x5E)

/* Status REGister */
#define SREG (*(volatile unsigned char *)0x5F)
/*Bit 7 – I: 全局中断使能     Bit 6 – T: 位拷贝存储,BLD 和BST利用T作为目的或源地址
  Bit 5 – H: 半进位标志    Bit 4 – S: 符号位, S = N ⊕ V
  Bit 3 – V:2 的补码溢出标志  Bit 2 – N: 负数标志
  Bit 1 – Z: 零标志    Bit 0 – C: 进位标志
*/
/* Port A bits */
#define  PORTA7   7
#define  PORTA6   6
#define  PORTA5   5
#define  PORTA4   4
#define  PORTA3   3
#define  PORTA2   2
#define  PORTA1   1
#define  PORTA0   0
#define  PA7      7
#define  PA6      6
#define  PA5      5
#define  PA4      4
#define  PA3      3
#define  PA2      2
#define  PA1      1
#define  PA0      0

#define  DDA7     7
#define  DDA6     6
#define  DDA5     5
#define  DDA4     4
#define  DDA3     3
#define  DDA2     2
#define  DDA1     1
#define  DDA0     0

#define  PINA7    7
#define  PINA6    6
#define  PINA5    5
#define  PINA4    4
#define  PINA3    3
#define  PINA2    2
#define  PINA1    1
#define  PINA0    0

/* Port B bits */
#define  PORTB7   7
#define  PORTB6   6
#define  PORTB5   5
#define  PORTB4   4
#define  PORTB3   3
#define  PORTB2   2
#define  PORTB1   1
#define  PORTB0   0
#define  PB7      7
#define  PB6      6
#define  PB5      5
#define  PB4      4
#define  PB3      3
#define  PB2      2
#define  PB1      1
#define  PB0      0

#define  DDB7     7
#define  DDB6     6
#define  DDB5     5
#define  DDB4     4
#define  DDB3     3
#define  DDB2     2
#define  DDB1     1
#define  DDB0     0

#define  PINB7    7
#define  PINB6    6
#define  PINB5    5
#define  PINB4    4
#define  PINB3    3
#define  PINB2    2
#define  PINB1    1
#define  PINB0    0

/* Port C bits */
#define  PORTC7   7
#define  PORTC6   6
#define  PORTC5   5
#define  PORTC4   4
#define  PORTC3   3
#define  PORTC2   2
#define  PORTC1   1
#define  PORTC0   0
#define  PC7      7
#define  PC6      6
#define  PC5      5
#define  PC4      4
#define  PC3      3
#define  PC2      2
#define  PC1      1
#define  PC0      0

#define  DDC7     7
#define  DDC6     6
#define  DDC5     5
#define  DDC4     4
#define  DDC3     3
#define  DDC2     2
#define  DDC1     1
#define  DDC0     0

#define  PINC7    7
#define  PINC6    6
#define  PINC5    5
#define  PINC4    4
#define  PINC3    3
#define  PINC2    2
#define  PINC1    1
#define  PINC0    0

/* Port D bits */
#define  PORTD7   7
#define  PORTD6   6
#define  PORTD5   5
#define  PORTD4   4
#define  PORTD3   3
#define  PORTD2   2
#define  PORTD1   1
#define  PORTD0   0
#define  PD7      7
#define  PD6      6
#define  PD5      5
#define  PD4      4
#define  PD3      3
#define  PD2      2
#define  PD1      1
#define  PD0      0

#define  DDD7     7
#define  DDD6     6
#define  DDD5     5
#define  DDD4     4
#define  DDD3     3
#define  DDD2     2
#define  DDD1     1
#define  DDD0     0

#define  PIND7    7
#define  PIND6    6
#define  PIND5    5
#define  PIND4    4
#define  PIND3    3
#define  PIND2    2
#define  PIND1    1
#define  PIND0    0


/* Lock and Fuse Bits with LPM/SPM instructions */

/* lock bits */
#define  BLB12    5
#define  BLB11    4
#define  BLB02    3
#define  BLB01    2
#define  LB2      1
#define  LB1      0

/* fuses low bits */
#define  BODLEVEL 7
#define  BODEN    6
#define  SUT1     5
#define  SUT0     4
#define  CKSEL3   3
#define  CKSEL2   2
#define  CKSEL1   1
#define  CKSEL0   0

/* fuses high bits */
//#define  RSTDISBL 7 //ATmega8
//#define  WDTON    6 //ATmega8
#define  OCDEN    7
#define  JTAGEN   6
#define  SPIEN    5
#define  CKOPT    4
#define  EESAVE   3
#define  BOOTSZ1  2
#define  BOOTSZ0  1
#define  BOOTRST  0

/* Interrupt Vector Numbers */
#define iv_RESET        1  //外部引脚,上电复位,掉电检测复位,看门狗复位
#define iv_INT0         2  //外部中断请求0
#define iv_INT1         3  //外部中断请求1
#define iv_INT2         4  //外部中断请求2
#define iv_TIMER2_COMP  5  //定时器/ 计数器2 比较匹配
#define iv_TIMER2_OVF   6  //定时器/ 计数器2 溢出
#define iv_TIMER1_CAPT  7  //定时器/ 计数器1 捕捉事件
#define iv_TIMER1_COMPA 8  //定时器/ 计数器1 比较匹配 A
#define iv_TIMER1_COMPB 9  //定时器/ 计数器1 比较匹配 B
#define iv_TIMER1_OVF   10 //定时器/ 计数器1 溢出
#define iv_TIMER0_COMP  11 //定时器/ 计数器0 比较匹配
#define iv_TIMER0_OVF   12 //定时器/ 计数器0 溢出
#define iv_SPI_STC      13 //SPI 串行传输结束
#define iv_USART_RX     14 
#define iv_USART_RXC    14 //USART, Rx 结束
#define iv_USART_DRE    15
#define iv_USART_UDRE   15 //USART 数据寄存器空
#define iv_USART_TX     16
#define iv_USART_TXC    16 //USART, Tx 结束
#define iv_ADC          17 //ADC 转换结束
#define iv_EE_RDY       18 //EEPROM 就绪
#define iv_EE_READY     18
#define iv_ANA_COMP     19 //模拟比较器
#define iv_ANALOG_COMP  19
#define iv_TWI          20 //两线串行接口
#define iv_TWSI         20
#define iv_SPM_RDY      21 //保存程序存储器内容就绪
#define iv_SPM_READY    21

/*外部时钟
CKSEL3..0  频率范围(MHz)  SUT1..0
0000    00    6 CK – BOD 使能
   01    6 CK 4.1 ms 电源快速上升
   10    6 CK 65 ms 电源缓慢上升
   11   保留
片内标定的RC 振荡器工作模式
0001 1    00   6 CK – BOD 使能
0010 2    01   6 CK 4.1 ms 电源快速上升
0011 4    10   6 CK 65 ms 电源缓慢上升
0100 8    11   保留
外部RC 振荡器工作模式
0101 <=0.9      00    18 CK – BOD 使能
0110 0.9-3    01    18 CK 4.1 ms 电源快速上升
0111 3-8        10    18 CK 65 ms 电源缓慢上升
1000 8-12    11   6 CK(1) 4.1 ms 电源快速上升,或是BOD 使能
低频晶体振荡器
1001 32.768 kHz     00    1K CK(1) 4.1 ms 电源快速上升,或是BOD 使能
       01    1K CK(1) 65 ms 电源缓慢上升
   10    32K CK 65 ms 启动时频率已经稳定
   11   保留
晶体振荡器  CKOPT 未编程时的最大频率为8 MHz,输出信号幅度比较小
1010 1   0.4-0.9  00 258 CK(1) 4.1 ms 陶瓷谐振器,电源快速上升
1100 1   0.9-3    01 258 CK(1) 65 ms 陶瓷谐振器,电源缓慢上升
1110 1   3-8    10 1K CK(2) – 陶瓷谐振器, BOD 使能
101,110,111 0   1<     11 1K CK(2) 4.1 ms 陶瓷谐振器,电源快速上升
1011 1   0.4-0.9  00 1k  CK(1) 65 ms 陶瓷谐振器,电源缓慢上升
1101 1   0.9-3    01 16k CK(1) – 石英振荡器, BOD 使能
1111 1   3-8    10 16k CK(2) 4.1 ms 石英振荡器,电源快速上升
101,110,111 0   1<     11 16k CK(2) 65 ms 石英振荡器,电源慢速上升
*/
 
/*WINAVR
// Interrupt vectors 

// External Interrupt Request 0
#define INT0_vect _VECTOR(1)
#define SIG_INTERRUPT0 _VECTOR(1)

// External Interrupt Request 1
#define INT1_vect _VECTOR(2)
#define SIG_INTERRUPT1 _VECTOR(2)

// External Interrupt Request 2
#define INT2_vect _VECTOR(3)
#define SIG_INTERRUPT2 _VECTOR(3)

// Timer/Counter2 Compare Match
#define TIMER2_COMP_vect _VECTOR(4)
#define SIG_OUTPUT_COMPARE2 _VECTOR(4)

// Timer/Counter2 Overflow 
#define TIMER2_OVF_vect _VECTOR(5)
#define SIG_OVERFLOW2 _VECTOR(5)

// Timer/Counter1 Capture Event 
#define TIMER1_CAPT_vect _VECTOR(6)
#define SIG_INPUT_CAPTURE1 _VECTOR(6)

// Timer/Counter1 Compare Match A
#define TIMER1_COMPA_vect _VECTOR(7)
#define SIG_OUTPUT_COMPARE1A _VECTOR(7)

// Timer/Counter1 Compare Match B
#define TIMER1_COMPB_vect _VECTOR(8)
#define SIG_OUTPUT_COMPARE1B _VECTOR(8)

// Timer/Counter1 Overflow 
#define TIMER1_OVF_vect _VECTOR(9)
#define SIG_OVERFLOW1 _VECTOR(9)

// Timer/Counter0 Compare Match 
#define TIMER0_COMP_vect _VECTOR(10)
#define SIG_OUTPUT_COMPARE0 _VECTOR(10)

// Timer/Counter0 Overflow
#define TIMER0_OVF_vect _VECTOR(11)
#define SIG_OVERFLOW0 _VECTOR(11)

// Serial Transfer Complete
#define SPI_STC_vect _VECTOR(12)
#define SIG_SPI _VECTOR(12)

// USART, Rx Complete 
#define USART_RXC_vect _VECTOR(13)
#define SIG_USART_RECV _VECTOR(13)
#define SIG_UART_RECV _VECTOR(13)

// USART Data Register Empty
#define USART_UDRE_vect _VECTOR(14)
#define SIG_USART_DATA _VECTOR(14)
#define SIG_UART_DATA _VECTOR(14)

// USART, Tx Complete
#define USART_TXC_vect _VECTOR(15)
#define SIG_USART_TRANS _VECTOR(15)
#define SIG_UART_TRANS _VECTOR(15)

// ADC Conversion Complete
#define ADC_vect _VECTOR(16)
#define SIG_ADC _VECTOR(16)

// EEPROM Ready
#define EE_RDY_vect _VECTOR(17)
#define SIG_EEPROM_READY _VECTOR(17)

// Analog Comparator
#define ANA_COMP_vect _VECTOR(18)
#define SIG_COMPARATOR _VECTOR(18)

// 2-wire Serial Interface
#define TWI_vect _VECTOR(19)
#define SIG_2WIRE_SERIAL _VECTOR(19)

// Store Program Memory Ready
#define SPM_RDY_vect _VECTOR(20)
#define SIG_SPM_READY _VECTOR(20)
*/

/*WINAVR
在程序中访问FLASH 程序存储器
#include <avr/pgmspace.h>
数据类型 变量名 PROGMEM = 值 ;如:
char val8 PROGMEM = 1 ;

pgm_read_byte(prog_void * addr)
pgm_read-word(prg_void *addr)
pgm_read_dword(prg_void* addr)

pgmspace.h 中定义的8 位整数类型 prog_char prog_uchar 分别指定在FLASH
内的8 位有符号整数和8 位无符号整数

EEPROM 数据存储器操作
#include <avr/eeprom.h>
这些函数有:
eeprom_is_ready() //EEPROM 忙检测(返回EEWE 位)
eeprom_busy_wait() //查询等待EEPROM 准备就绪
uint8_t eeprom_read_byte (const uint8_t *addr) //从指定地址读一字节
uint16_t eeprom_read_word (const uint16_t *addr) //从指定地址一字
void eeprom_read_block (void *buf, const void *addr, size_t n) //读块
void eeprom_write_byte (uint8_t *addr, uint8_t val) //写一字节至指定地址
void eeprom_write_word (uint16_t *addr, uint16_t val) //写一字到指定地址
void eeprom_write_block (const void *buf, void *addr, size_t n) //写块

void my_init_portb (void) __attribute__ ((naked)) \
__attribute__ ((section (".init1")));
void my_init_portb (void)
{
PORTB= 0xff;
DDRB=0xff;
}
使用__arrribute__关键字为函数指定属性要在函数的原型声明上,而不是函数的实现例
程里。由于属性section(“.init1”)的指定,编译后函数my_init_portb 生成的代码自动插入
到.init1 段中,在main 函数前就得到执行。naked 属性确保编译后该函数不生成返回指令,
使下一个初始化段得以顺序的执行。

中断服务程序
SIGNAL(signame)和INTERRUPT(signame)。
宏INTERRUPT 的用法与SIGNAL 类似,区别在于SIGNAL 执行时全局中断触发位被
清除、其他中断被禁止,INTERRUPT 执行时全局中断触发位被置位、其他中断可嵌套执行。

signame 中 断 类 型
SIG_INTERRUPT0 外部中断INT0
SIG_INTERRUPT1 外部中断INT1
SIG_OUTPUT_COMPARE2 定时器/计数器比较匹配中断
SIG_OVERFLOW2 定时器/计数器2 溢出中断
SIG_INPUT_CAPTURE1 定时器/计数器2 输入捕获中断
SIG_OUTPUT_COMPARE1A 定时器/计数器1 比较匹配A
SIG_OUTPUT_COMPARE1B 定时器/计数器1 比较匹配B
SIG_OVERFLOW1 定时器/计数器1 溢出中断
SIG_OVERFLOW0 定时器/计数器0 溢出中断
SIG_SPI SPI 操作完成中断
SIG_UART_RECV USART 接收完成
SIG_UART_DATA USART 寄存器空
SIG_UART_TRANS USART 发送完成
SIG_ADC ADC转换完成
SIG_EEPROM_READY E2PROM 准备就绪
SIG_COMPARATOR 模拟比较器中断
SIG_2WIRE_SERIAL TWI 中断
SIG_SPM_READY 写程序存储器准备好

以下是个外部中断0 的重写示例:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
SIGNAL(SIG_INTERRUPT0)

看门狗应用
#include <avr/wdt.h>
wdt_reset() // Watchdog 复位
wdt_enable(timeout) // Watchdog 使能
wdt_disable() // Watchdog 禁止
符号常量 值含意
WDTO_15MS Watchdog 定时器15 毫秒超时
WDTO_30MS Watchdog 定时器30 毫秒超时
WDTO_60MS Watchdog 定时器60 毫秒超时
WDTO_120MS Watchdog 定时器120 毫秒超时
WDTO_250MS Watchdog 定时器250 毫秒超时
WDTO_500MS Watchdog 定时器500 毫秒超时
WDTO_1S Watchdog 定时器1 秒超时
WDTO_2S Watchdog 定时器2 秒超时

C 代码中内联汇编程序
asm("in %0,%1 " : "=r " (value) : "I" (_SFR_IO_ADDR(PORTD)));
asm(code:output operand list : input operand list [: clobber list])
如上声明格式,四部分之间用符号 “:”隔开,Clobber 寄存器指示部分空时可以忽略,
其它部分可空但不可忽略。例如:
asm volatile(“cli” : : );
专用寄存器定义
符 号 寄 存 器
__SREG__ 状态寄存器 SREG(0X3F)
__SP_H__ 堆栈指针高字节(0X3E)
__SP_L__ 堆栈指针低字节 (0X3E)
__tmp_reg__ R0
__zero_reg__ R1,对C 代码来说其值永远为0

操作作数约束符
约束符号 适用于 范围
a 后半部分寄存器 R16~R23
b 指针 Y,Z
d 后半部分寄存器 R16~R31
e 指针 X,Y,Z
G 浮点常数 0.0
I 6 位正常数 0~63
J 6 位正常数 -63~0
K 常整数 2
L 常整数 0
l 前半部分寄存器 R0~R15
M 8 位正常数 0~255
N 常整数 1
O 常整数 8,16,24
P 常整数 1
q 堆栈指针寄存器 SPH:SPL
r 全部寄存器 R0~R31
t 暂存寄存器 R0
w 寄存器对 R24,R26,R28,R30
x 指针X
y 指针Y
z 指针Z
修饰符 意义
= 只 写
+ 读 写(内联汇编不支持)
约束符前可加的
修饰符
& 寄存器只用做输出

嵌入语句  编译结果
asm volatile(“cli;
ld r24,%a0;
inc r24;
st %a0,r24;
sei”
:
: “z”(ptr)
: “r24”
);

CLI
LD R24,Z
INC R24
ST Z,R24

C 编译器使用寄存器约定
(1)r0 和r1 :在C 程序中这两个寄存器用于固定目的,从不分配局部变量。
r0 是暂存寄存器,在汇编程序中可以自由的使用,若在汇编程序中使用了r0 并且要调
用C 函数则必需在调用C 函数前要保存它。若在中断函数中使用此寄存器要在使用前保存,
和退出时恢复,C 中断函数会自动保存的恢复r0。
r1 是零寄存器,C 编译器总认为其内容为零。如果汇编程序要使用这个寄存器,则在汇
编代码返回之前要清零它。中断函数要使用r1 则必需在退出时将其清零,C 中断函数会自
动保存的恢复r1。
(2)r2-r17、r28-r29:
局部变量分配寄存器,汇编程序若改变了这些寄存器内容,则必需恢复其内容。
(3)r18-r27、r30-r31
局部变量分配寄存器,汇编程序可自由的使用这此寄存器,无需恢复,但若在汇编程序
中使用了这些寄存并要调用C 函数,则需在调用前保护所用的寄存器。
SEI

flash区常量的初始化:
prog_char c='A';
prog_int a=1234;
prog_char str[]="string";
PGM_P pstr;
pstr=PSTR("static strings");//字符串"static strings"在flash区,宏PSTR(获得静态字符串指针)只能在函数中使用。
flash区常量的读取:
读字符:pgm_read_byte(address_short)
读字:pgm_read_word(address_short)
读n个字符/字节:void *memcpy_P(void *, PGM_VOID_P, size_t) //void * 指目的指针(在SRAM)
读字符串:char *strcpy_P(char *, PGM_P)
其他内容参阅pgmspace.h和avr-libc用户手册
2.访问或定义flash区常量应注意的问题
flash区常量是不可见的,不能用常规 的方法来读取/定义,比如:
//拼音索引表结构定义
struct t9PY_index
{
    PGM_P    t9PY_T9;
    PGM_P    PY;
    PGM_P    PY_mb;
};
const prog_char PY_mb_space []PROGMEM={""};
const prog_char PY_mb_a     []PROGMEM={"@啊阿"};
...
}
//"拼音输入法查询码表,T9数字字母索引表(index)"
const struct t9PY_index  t9PY_index2[]PROGMEM =
{
  {"","",PY_mb_space},
  {"2","a",PY_mb_a},
  ..
}
结构定义中的所有域都定义成PGM_P,按理拼音输入法查询码表t9PY_index2所有数据都应放在flash区,但事实并不这样,“”、“2”、“a"
却放在.data段(SRAM),不管在字符串常量前加强制类型转换,这是因为GCC把全局或静态常量强制放在.data段(SRAM),解决的方法是
字符串常量换成常量标识符:
const prog_char digits_2[]="2";
..
const prog_char alpha_a[]="a";
..
const struct t9PY_index  t9PY_index2[]PROGMEM =
{
{PY_mb_space,PY_mb_space,PY_mb_space},
{digits_2,alpha_a,PY_mb_a},
..
}
PGM_VOID_P p_PY_CurrenIndex;//指向拼音输入法查询码表的指针
指向flash 结构指针或结构类型不能用指向符或域引用符获取结构的域成员,如(struct t9PY_index) p_PY_CurrenIndex->t9PY_T9。
正确方法:
  struct t9PY_index PY_TempIndex;
  char  temp_t9PY_T9[8],*str;
  memcpy_P(&PY_TempIndex,p_PY_CurrenIndex,sizeof(struct t9PY_index));
  strcpy_P(temp_t9PY_T9,PY_TempIndex.t9PY_T9);
  str=strstr(temp_t9PY_T9,p_PadInput); 
*/
/*IAR中生成HEX
LINK/Extro Option加上: 

-Ointel-standard,(CODE)=.hex  
-Oraw-binary,(CODE)=.bin 
-Ointel-standard,(XDATA)=.eep.hex  
-Oraw-binary,(XDATA)=.eep.bin
*/
#endif
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个基于你的要求的ICCAVR代码,用于验证LCD1602是否能够正常亮,并且RS连接到PD7,RW连接到PD6,E连接到PD5,双向数据线连接到PC口: ``` #include <iom16v.h> #include <macros.h> #include <util/delay.h> #define LCD_DATA_DIR DDRC // 将LCD数据线连接到MCU的PC0-PC7引脚 #define LCD_DATA_PORT PORTC #define LCD_CTRL_DIR DDRD // 将LCD控制线连接到MCU的PD5-PD7引脚 #define LCD_CTRL_PORT PORTD #define RS PD7 // 将LCD的RS引脚连接到PD7 #define RW PD6 // 将LCD的RW引脚连接到PD6 #define E PD5 // 将LCD的E引脚连接到PD5 void lcd_command(unsigned char cmnd) { LCD_DATA_PORT = cmnd; LCD_CTRL_PORT &= ~(1<<RS); // 将RS引脚设为低电平,表示发送的是命令 LCD_CTRL_PORT &= ~(1<<RW); // 将RW引脚设为低电平,表示写入数据 LCD_CTRL_PORT |= 1<<E; _delay_us(1); LCD_CTRL_PORT &= ~(1<<E); _delay_ms(3); } void lcd_init(void) { LCD_DATA_DIR = 0xFF; // 将PC0-PC7引脚设为输出模式 LCD_CTRL_DIR |= (1<<RS) | (1<<RW) | (1<<E); // 将PD5-PD7引脚设为输出模式 LCD_DATA_PORT = 0xFF; LCD_CTRL_PORT &= ~(1<<RS); // 将RS引脚设为低电平,表示发送的是命令 LCD_CTRL_PORT &= ~(1<<RW); // 将RW引脚设为低电平,表示写入数据 LCD_CTRL_PORT &= ~(1<<E); _delay_ms(20); lcd_command(0x38); // 8位数据,2行显示,5x7点阵字符 lcd_command(0x0C); // 打开LCD显示,关闭光标显示 lcd_command(0x06); // 光标自动右移 lcd_command(0x01); // 清除显示 _delay_ms(2); } void lcd_write_char(unsigned char data) { LCD_DATA_PORT = data; LCD_CTRL_PORT |= 1<<RS; // 将RS引脚设为高电平,表示发送的是数据 LCD_CTRL_PORT &= ~(1<<RW); // 将RW引脚设为低电平,表示写入数据 LCD_CTRL_PORT |= 1<<E; _delay_us(1); LCD_CTRL_PORT &= ~(1<<E); _delay_ms(1); } int main(void) { LCD_DATA_DIR = 0xFF; // 将PC0-PC7引脚设为输出模式 LCD_CTRL_DIR |= (1<<RS) | (1<<RW) | (1<<E); // 将PD5-PD7引脚设为输出模式 lcd_init(); // 初始化LCD lcd_write_char('H'); lcd_write_char('e'); lcd_write_char('l'); lcd_write_char('l'); lcd_write_char('o'); while(1) { } } ``` 这个代码会向LCD1602屏幕上写入"Hello"这个单词。如果屏幕正常亮起并显示该单词,则表明LCD1602模块能够正常工作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值