Timer/Counter 和 Interrupt
Timer/Counter2 产生PWM控制LCD背光亮度
因为我用PD7引脚产生的PWM去控制LCD的背光的亮度,查找PD7对应的Alternate Function是 Timer/Counter2 Output Compare Match Output, 所以对应使用Timer/Counter2
TCCR2 配置
BIT | Function | 配置 | 说明 |
---|---|---|---|
7 | Force Output Compare | 0 | 不用管,自己设置为0就好 |
3,6 | WGM2(1:0): Waveform Generation Mode | 11 | 设置成Fast PWM 模式 |
5:4 | COM2(1:0): Compare Match Output Mode | 11 | 因为需要输出,所以Set OC2 on compare match |
2:0 | CS2(2:0): Clock Select | 000 | 这个是时钟分频,开心就好,这里没有所谓 |
因为在这里只是单纯的PWM输出,在系统内不需要中断来对应操作,所以其他的配置中断什么的寄存器不用管。
然后直接设置ORC2这个寄存器就好,会根据这个寄存器的值,来控制PWM占空比。
Timer/Counter 1 配置定时器中断
使用 Timer/Counter 1 的定时器中断来控制整个系统,例如贪吃蛇游戏里,需要大概1秒钟蛇移动一格,因此在一次定时器中断中,控制蛇移动一格。所以在 Timer/Counter 1 中主要是配置去控制进入中断的时间。
Timer/Counter 1 有很多模式,在这里配置的是用Normal Mode,因此很多寄存器直接使用默认的就好,所以只需要写TCNT1H, TCNT1L, TIMSK TCCR1B 这几个寄存器就好,其他的就默认配置成 Normal Mode
TIMSK
因为使用的是Normal Mode 直接是overflow的中断,所以在TIMSK将TOIE1(Timer/Counter1, Overflow Interrupt Enable) 设置为1就好。
TCCR1B
查询 DATASHEET 113页面, WGM1 都是0 ICNC1和ICES1不需要管,只需要配置时钟分频即可。使用的外部晶振是8MHz,为了计算方便,使用8分频到1MHz,因此CS1(2:0)配置为010即可。
TCNT1
TCNT1 就是 value of the counter, 在 Normal Mode 中 TCNT1 计数到16位满之后,产生overflow中断(这一点也对应中断向量)。由于计数器的时钟分频后得到1MHz,以及16位对应最大的十进制数是65535,因此选个好计算的数50000作为计数的个数,从而每1/20秒(50ms)产生一次中断。 所以计算65535-50000 = 15535对应16进制数为0x3CAF,
TCNT1分为两个部分TCNT1H和TCNT1L
TCNT1H = 0X3C;
TCNT1L = 0XAF;
即可。
按键中断
如果在while循环中每次都要检测按键按下的情况,特别浪费资源,因此,当有一个按键按下的时候,进入中断,然后检测是哪一个按键按下后,再进行按键的检测。
我在原理图上连接的按键中断是到PD2,对应的是Alternate Function 是External Interrupt 0 Input,所以之后配置INT0 即可
配置GICR(General Interrupt Control Register)
DATASHEET 48页对应寄存器说明,IVSEL和IVCE可以不用管(没有管能配置出来中断,就没管了)
设置INT0位为1即可
配置MCUCR (MCU Control Register)
中断可以配置成4种模式,低电平,任何逻辑,上升沿,下降沿。一般而言选择当有按键按下时进行进行中断触发,因此选择上升沿出发。
对应在INT0中的上升沿出发,配置ISC0(1:0) = 11 即可。
LCD
SPI Configuration
In SPI, the uController is master and the LCD is the slave, so set the SCK, MOSI pin as the OUTPUT and MISO as INPUT.
Then from page 138 in ATMEGA16 DATASHEET, in initialization, just configure SPCR.
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
Then, the uController can send data by this function
void SPI_MasterTransmit(char cData)
{SPDR = cData;
while(!(SPSR & (1<<SPIF)));
}
LCD Configuration
Send Command
LCD_CS set 0 , because the CS pin in LCD is negative logic.
LCD_CD set 0 , which means what the MOSI send is COMMAND.
Using SPI send COMMAND.
LCD_CS set 1
Send Data
LCD_CS set 0 , because the CS pin in LCD is negative logic.
LCD_CD set 1 , which means what the MOSI send is DATA.
Using SPI send DATA.
LCD_CS set 1
Initialization
The Initialization code can be found in LMS.
Select Page
Some basic thing you should know what is Column and Page, which is illustrated in page 6 in LCD_dogs102-6e.pdf
From page 12 in LCD controller DATASHEET, the high 4 bits of COMMEND is 1011(binary) and the low 4 bits of COMMAND is the page number.
For example,
LCD_command_tx(0xB2);
this example select page 2 in LCD.
Select Column
Since there are 0~101 columns in LCD, the bits of columns are more than 4 bits, so it cannot be selected as page.
Actually, the number of columns can be expressed by 8 bits, which be divided to two 4 bits.
for example
LCD_command_tx(0x02);
LCD_command_tx(0x12);
this example select 34th(0x22) columns.
Send Data to draw
After we have selected the Column and Page, we can send data to draw something on LCD.
simple example
LCD_command_tx(0x02);
LCD_command_tx(0x12);
LCD_command_tx(0xB2);LCD_data_tx(0xFF);
this example select 34th column and 2nd page. And then write all of this part 1, so there shoud be a line on 34th column and 2nd 8 pixels. Actually is 35 column and 3rd 8 pixels, becasue in code, everything start from 0 not 1.