资源描述
PC = progammer counter //程序计数器
ACC = accumulate //累加器
PSW = progammer status word //程序状态字
SP = stack point //堆栈指针
DPTR = data point register //数据指针 寄存器
IP = interrupt priority //中断优先级
IE = interrupt enable // 中断使能
TMOD = timer mode //定时器 方式 (定时器/计数器 控制寄存器)
ALE = alter (变更,可能是)
PSEN = progammer saving enable //程序存储器使能(选择外部程序存储器的意思)
EA = enable all(允许所有中断)完整应该是 enable all interrupt
PROG = progamme (程序)
SFR = special funtion register //特殊功能寄存器
TCON = timer control //定时器控制
PCON = power control //电源控制
MSB = most significant bit//最高有效位
LSB = last significant bit//最低有效位
CY = carry //进位(标志)
AC = assistant carry //辅助进位
OV = overflow //溢出
ORG = originally //起始来源
DB = define byte //字节定义
EQU = equal //等于
DW = define word //字定义
E = enable //使能
OE = output enable //输出使能
RD = read //读
WR = write //写
中断部分:
INT0 = interrupt 0 //中断0
INT1 = interrupt 1//中断1
T0 = timer 0 //定时器0
T1 = timer 1 //定时器1
TF1 = timer1 flag //定时器1 标志 (其实是定时器1中断标志位)
IE1 = interrupt exterior //(外部中断请求,可能是)
IT1 = interrupt touch //(外部中断触发方式,可能是)
ES = enable serial //串行使能
ET = enable timer //定时器使能
EX = enable exterior //外部使能(中断)
PX = priority exterior //外部中断优先级
PT = priority timer //定时器优先级
PS = priority serial //串口优先级
第一部分
二极管发光的条件是 正负极 相差达1V以上。
AVR单片机控制负极更好。
用单片机的IO口去控制二极管的负极从而控制二极管。
IO复位后全部为输入工作方式内部上拉电阻无效,IO是三态高阻的状态
IO工作时读取外部引脚的电平一定要用PINXN这个才是反应真正的电平
AVR工作电源是5V
灯泡的DDRA=0XFF PORTA=0X00
LED灯管的DDRB=0XFF PORTB=0X00的时候量的
开关的时候是DDRB=0X00 PORTB=0XFF 打开不闭合不导通当PORTB=0的时候导通
让LED亮
#include <avr/io.h>
int main (void)
{DDRA=0xFF;
DDRB=0xFF;
PORTA=0xC0;PORTB=0xf7;
while (1)
{
}
}#include<avr/io.h>
#include<avr/delay.h>
unsigned char digit[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
按键开关
int main(void)
{
DDRA=0xff;
PORTA=0x00;
DDRB=0xff;
DDRD=0x00;
PORTD=0xff;
while (1)
{
if((PIND^0xff)==4) {PORTA=0xF9; _delay_ms(1000);}
else
if ((PIND^0xff)==8){ PORTA=0xA4; _delay_ms(1000);}
else
if((PIND^0xff)==0x10) { PORTA=0xb0; _delay_ms(1000);}
else
if((PIND^0xff)==0x20) {PORTA=0x99; _delay_ms(1000);}}
}
按键按一下后弹起
#include<avr/io.h>
#include<avr/delay.h>
#define F_CPU 800000UL
unsigned char digit[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
int main(void)
{
DDRA=0xff;
PORTA=0x00;
DDRB=0xf8;
DDRD=0X00;
PORTD=0XFF;
int i;
while(1)
{
if(~PIND&0x04) //保证其位为0
{
PORTA=digit[1];
_delay_ms(100);
}
else PORTA=digit[0];
}
}
第二部分 SPI通信
第三部分数码管
数码管由8段组成A B C D E F G P . 8 个连接在一起的发光二极管。
两种:共阳形 共阴行。
驱动方式:静态驱动, 动态驱动.
静态:一个IO 端口控制一个数码管。方便,耗电量大,占用资源多。
动态:一位一位动态点亮各个数码管。每隔一段时间点亮一次。占用资源少,不易控制。
8个段码加上几个位选。几个位选代表几个数码管。
数码管驱动芯片:CH451,
CH451可以驱动8个数码管 或者64个发光二极管。串行数据的输入顺序是低位在前,高位在后。
CH451有4个串行接口;
4个:DIN DCLK LOAD DOUT .
DIN(输入线) DCLK(时钟线) LOAD(加载线) 是带上拉的输入信号线,默认是高电平。
DOUT 串行数据输出线。
第四部分引脚
电源:VCC (电源)AVCC(模拟电源)GND
RESTE 外部复位脚
单片机一般是低电平复位。在RESTE上给一个低电平使其复位。
XTAL1 XTAL2 时钟
CH451的扫描顺序为DIG0-DIG7 一个引脚吸入电流时,其他引脚不吸入电流。
降低扫描极限可以提高数码管的亮度。
CH451有8个8位的数据寄存器。
第五部分 键盘(PD的高四位作为输出口
低四位作为输入口 列线作为输入端 行线作为输出端)
独立键盘:
根据电平的不同来判断是否按下。机械弹性触电开关。
按键抖动
键盘的消抖
硬件消抖:加入消抖电路(难度大)
软件消抖:软件设计(第一次确认后经过10MS再确认按键是否按下)
上拉电阻使能?
(PORTXN=1 PUD=1 DDRXN=0)三个条件都满足时表示上拉电阻有效。
当PORTXN=0表示其上拉电阻无效。
矩阵键盘:反转法 和逐行扫描矩阵(由行线列线构成)
按键未按下时是高电平,按下变成低电平
电平 与信号
一个键盘对应一个IO口
IO 口有三态?上拉电阻
逐行扫描法:
确定有键按下:4行全部是低电平 4列全部是高电平
确定后确定哪个键按下 依次将行线设置为低电平 列线全部为高电平
PA0-PA3控制行 PA4-PA7控制列
输出端是不变的 如果输入端是低电平 输出端为高电平
输如端变为高电平
程序
#include <avr/io.h>
#include <utile/delay.h>
unsigned char read_key(void)
unsigned char i,j,key_value=0xff;
DDRD=0xf0;
PORTD=0x0f;
if((PIND&0x0f) return Oxff;
else {
delay_ms(5);
if((PIND&0x0f)==0x0f) return 0xff;
else
{
for (i=4;i<8;i++)
{
PORTD=~(1<<i)|0x0f;
for(j=0;j<4;j++)
{
if((PIND&(1<<j)==0)
key_value=(i-4)*4+j;
}
}
return key_value;
}
}
int main ()
{
//
}
第六部分:中断
中断:自动响应请求 执行中断请求服务 再回来。
优点:
实时处理
实现分时操作
进行故障处理
待机状态的唤醒
几个概念:
主程序
中断源:可以发出单片机的CPU中断请求的部件和设备
(分类:非屏蔽中断 可屏蔽中断 软件中断)
中断请求信号:发出的申请信号
中断标志:对应的不同中断标志位有不同的变化
中断响应:停止现行程序 转向中断服务程序
中断服务程序:中断要做到事情 转向
断点:被打断的地方
中断现场保护
中断返回
中断向量
中断优先级(由硬件决定)
中断嵌套
响应A中断=全局中断标志 中断A允许标志 中断A标志(三个条件) 针对可屏蔽中断
ATMEGE16共21个中断源 每个中断向量占2个字(4个字节)
中断响应过程:
第一:全局允许中断位清0 禁止响应其它中断 被响应的中断标志位清0 将中断的断点的地址压入堆栈 自动将响应中断向量地址压入程序计数器(中断服务程序的入口地址)
至少4个时钟周期
中断返回的过程
程序:
几个寄存器
MCUCR(ISC11 ISC10)控制INT1(ISC01 ISC00)控制INT0
GICR (当它是1时开启中断)(中断使能寄存器)
GIFR( 外部中断标志器)
#define F_CPU 7372800UL //定义时钟频率,保证delay函数的准确
键盘中断
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>
int num_tab[10]={0xc0,0xf9,0xa4,
0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //显示数字时对应的PA口信号
void led_num(unsigned int num) //数字输出函数
{
unsigned char temp,i;
for(i=0;i<4;i++)
{
PORTB=0XFF;
temp=num%10;
PORTA=num_tab[temp];
PORTB=~(1<<(3-i));
_delay_us(20);
num/=10;
}
}
//中断
SIGNAL(SIG_INTERRUPT0) //外部中断0所执行程序的内容
{
sei(); //开总中断
PORTB=0X00;
PORTA=0xf0;
while(1);
}
SIGNAL(SIG_INTERRUPT1) //外部中断1所执行程序的内容
{
sei(); //开总中断
PORTB=0X00;
PORTA=0x0f;
while(1);
}
void IO_init(void) //端口初始化
{
PORTA=0XFF;
DDRA=0XFF;
PORTB=0XFF;
DDRB=0XFF;
PORTC=0xff;
DDRC=0xff;
PORTD=0xff;
DDRD=0x00;
}
void interrupt_init(void) //中断初始化
{
MCUCR=0X03; //中断0、1为上升沿产生中断请求,
GICR=0xc0; //开中断0、1
}
int main(void)
{
IO_init(); //端口初始化
interrupt_init(); //中断初始化
sei(); //开总中断
unsigned int a,b;
while(1)
{
for(a=0;a<9999;a++)
{
for(b=0;b<5000;b++)
led_num(a); //输出信号
}
}
}
按键中断的起始条件:
DDRA=0XFF;
DDRB=0XFF;
DDRD=0X00;
PORTD=0XFF;
中断函数
SIGNAL(SIG_INTERRUPT0)
void interrupt_init(void) //中断初始化
{
MCUCR=0X03; //中断0、1为上升沿产生中断请求,
GICR=0xc0; //开中断0、1
}
计时器计数器
定时计数器的长度 8位16位
脉冲信号源 外部引脚 和内部提供
计数器的类型 +1 -1
上下限 最小值 最大值
计数器的事件 比较匹配中断
2个八位 一个16位的计数器
主要是8位
T/C0
1单通道计数器
2比较匹配清0计数器
3允许使用外部引脚
4 10位的时钟分频器和频率发生器
5 溢出和比较匹配中断源
6 输出PWM信号
中断方式:溢出中断 比较中断
时钟源
外部时钟源 同步采样电路 边缘检测电路
外部频率至少不能大于系统的 2.5分之一
宽度大于一个系统时钟周期
定时器的计数单元 +1 或者-1 或者 清0
比较匹配中断 输出比较寄存器 TCNT OCRN 两者相等时 输出中断 标志位置为1
为什么有些是到255?
定时器的工作模式:
普通模式
比较模式
PWM模式
TCNTO 记录初值
输出比较寄存器OCRO
TIMSK
TIFR
TCCRO 控制寄存器 调节工作模式
用的是 WGM00 WGM01
CS02 CS01 CS02 0选择时钟源
1 1 0 下降沿触发
1 1 1 上升沿触发
void timer0_init() //计时器T0初始化
{
TCNT0 = 0;
TCCR0 |= (1<<CS00)|(1<<CS02);//1024分频
TIMSK |=(1<<TOIE0); //TO中断溢出允许
}
//ISR(TIMER0_OVF_vect)
SIGNAL(SIG_OVERFLOW0) //T0中断溢出函数
{
n+=1;
}
两个独立的中断源:
溢出中断TOVO 输出比较中断0CF0
总结
TCCRO T/C控制寄存器
是用来控制信息源的类别和模式的
TCNTO T/C寄存器
OCRO 输出比较寄存器
TIMSK T/C中断屏蔽寄存器
TIFR 中断标志寄存器
当TIMSK=0X01时是溢出中断
当TIMSK=0X02时是比较中断
中断标志寄存器是不用我们定义的 电脑运行的时候中断执行会把它变为1
中断使能的意思是 这个中断可以运行.
问:
0CR0=0XFF的时候CTC模式等于普通模式.
CTC与快速PWM的区别是两着的TOP不同,
快速PWM模式改变波形:
改变有效值(有效电压)
快速PWM模式
在比较匹配的时候电平变为0 达到最大值的时候(0XFF)变为1
0C0是在PB3上的 打开这个端口是DDRB=0X04
当有输出的时候要打开0CO
不是所有的比较输出都要打开0C0的主要看要不要输出
0CR0是那个比较的数值.
TCO 八位计时器
TC1十六位计时器
使用内部时钟源计时
使用外部时钟源用来计数
{TCNTO=0X00;
TCCRO=0X07;
TIMSK|=(1<<TOIEO);
}
要发生中断要按255次1号按键 T0对应PB0 按键可以吗?
PB0好像没有按键.
在普通模式中 当他完成溢出中断的时候他是返回原值 还是0X00?
0X00
在CTC模式的时候是返回原值的。
脉冲宽度调节PWM 可以得到不同的电压输出。用电平控制电机。
频率
占空比 相位 PWM的频率要大于42HZ 这样人眼观测不到灯的亮暗变化。PWM频率越高电压越平尾。PWM是数字脉冲。
PWM定时器产生正弦波
采样频率至少为信号频率的2倍
为16KHZ 每隔8个点采样
第N 部分
模数转换器ADC
中断标志位?什么用的?
不懂?是不是不用我们自己定义,发生中断的时候系统自己会改的?
第九部分:
SPI 通信
CPOL=0 空闲是低电平 启动变为高电平
=1时相反
CPHA=0是 起始沿为采样 结束沿为设置
问:
中断的条件:
中断允许为为1,全局中断为1,那个中断使能为为1?
顺序是则么样的?
只有当SS被拉低的时候SPI才开始工作。
数据的LSB MSB 是不是都是对于16位数而言的?
MOSI 主出从入
MISO 从出主入
主机的时候要主动控制SS 引脚
作为主机的时候 SS口为输出
从机的时候为输入 外部主机控制引脚不需要认为控制
在SS至高的时候可以跟新SPDR里面的内容。
SPI 是一个字节一个字节移位的吗? 是的
一个字节完全移出之后,传输结束标志 是的。传递是一个位一个位来的。
SPIF置位。如果此时SPCR寄存器的SPI中断使能位SPIE置位,就会产生中断请求。
MSB,LSB是最高有效位和最低有效位,也就是首位和尾位
SPI 系统的发送方向只有一个缓冲器,而在接收方向有两个缓冲器。
SS至高的时候是不是SPI不能传递数据
如果SS 配置为输入,必须保持为高以保证SPI 的正常工作。
如果MSTR为"1”,SS配置为输入,但被拉低,则MSTR 被清零,寄存器SPSR 的SPIF 置位。
SCK
138页中的那两个PIN是什么意思?
MSB first (DORD = 0)
LSB first (DORD = 1)
对的
仔细看程序
SPI
DDRB =0XFF; //低四位输出低电平,使四位数码管均作显示
PORTB=0XF0;?SSzhi gao
第十部分ADC
ADC 控制和状态寄存器A -ADCSRA
ADC 多工选择寄存器- ADMUX
ADC 数据寄存器- ADCL 及ADCHSSS
特殊功能IO 寄存器- SFIOR
ADC中的分辨率指的是什么?
ADC的结果是补码的形式
模拟信号要尽可能短.
PA口有输入..模式并且关闭上拉电阻
第11部分 USART
异步传输
异步通信是采用异步传输方式实现数据交换的一种方式.
波特率:数据位的宽度
数据帧格式
特点:
全双工操作
支持同步异步传输
独立的高精度波特率发生器
4种模式:
………..
数据寄存器UDR 包括一个发送一个接收 但是占用同一个地址.
只有在数据寄存器是空的时候才能被写入.
USART 控制和状态寄存器A -UCSRA
• Bit 7 – RXC: USART 接收结束
数据接受完成但还是没有被读出去的时候置1
• Bit 6 – TXC: USART 发送结束
数据发送完置1……。TXC 标志可用来产生发送结束中断.
• Bit 5 – UDRE: USART 数据寄存器空
UDRE为1说明缓冲器为空,已准备好进行数据接收.
• Bit 4 – FE: 帧错误
不懂?出错的时候会置为1.
• Bit 2 – PE: 奇偶校验错误
Bit 0 – MPCM: 多处理器通信模式
USART 控制和状态寄存器B -UCSRB
• Bit 7 – RXCIE: 接收结束中断使能
• Bit 6 – TXCIE: 发送结束中断使能
• Bit 5 – UDRIE: USART 数据寄存器空中断使能
• Bit 4 – RXEN: 接收使能
? RxD 引脚的通用端口功能被USART 功能所取代。?
• Bit 3 – TXEN: 发送使能
• Bit 2 – UCSZ2: 字符长度
• Bit 1 – RXB8: 接收数据位 8
• Bit 0 – TXB8: 发送数据位8
USART 控制和状态寄存器C -UCSRC
USART 波特率寄存器- UBRRL
和UBRRH
USART 接受以下30 种组合的数据
帧的格式:
• 1 个起始位
• 5、 6、 7、 8 或9 个数据位
• 无校验位、奇校验或偶校验位
• 1或2 个停止位
数据帧以起始位开始
波特率改变了,正在进行的接受将被打断.
UBRRH UCSRC 两者占用相同的IO 口 用最高位URSEL来设置
URSEL =0是写入的是UBRRH 波特率的高四位
URSEL=1是写入的是UCSRC
USART的初始化包括波特率的设定 帧结构的设定以及根据需要使能发送器和接收器.
改变USART 要在没有数据传输的情况下进行
TXC检查数据是否发送完成
RXC检查接受缓存器中是否还有数据
每次放送前TXC必须清0。
数据中中断?
不懂
中断执行时自动清0 也可以写“1”清0.不懂?
以9位数据接收的时候必须先接收第九位数据,
初始化
void USART_Init( unsigned int baud )
{
/* 设置波特率*/
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
/* 接收器与发送器使能*/
UCSRB = (1<<RXEN)|(1<<TXEN);
/* 设置帧格式: 8 个数据位, 2 个停止位*/
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
USART 发送器
void USART_Transmit( unsigned char data )
{
/* 等待发送缓冲器为空 */
while ( !( UCSRA & (1<<UDRE)) )
;
/* 将数据放入缓冲器,发送数据 */
UDR = data;
}
9位的帧
void USART_Transmit( unsigned int data )
{
/* 等待发送缓冲器为空 */
while ( !( UCSRA & (1<<UDRE))) )
;
/* 将第9 位复制到TXB8 */
UCSRB &= ~(1<<TXB8);
if ( data & 0x0100 )
UCSRB |= (1<<TXB8);
/* 将数据放入缓冲器,发送数据 */
UDR = data;
}
当UCSRB 寄存器中的数据寄存器空中断使能位UDRIE 为"1” 时,只要UDRE 被置位(且全局中断使能),就将产生USART 数据寄存器空中断请求。对寄存器UDR 执行写操作将清零UDRE。当采用中断方式的传输数据时,在数据寄存器空中断服务程序中必须写一
个新的数据到UDR 以清零UDRE ;或者是禁止数据寄存器空中断。否则一旦该中断程序结束,一个新的中断将再次产生。
USART 数据寄存器空标志UDRE 及传输结束标志TXC,
这两个中断有区别:UDRE在执行完中断后部能变回0
接收与发送的顺序
接收缓存寄存器 接收移位寄存器
发送的时候:
发送缓存器 到发送移位寄存器
接收的时候:
接收寄存器 接收缓存器
unsigned char USART_Receive( void )
{
/* 等待接收数据*/
while ( !(UCSRA & (1<<RXC)) )
;
/* 从缓冲器中获取并返回数据*/
return UDR;
}
接收结束标志(RXC)
刷新接收器
void USART_Flush( void )
{
unsigned char dummy;
while ( UCSRA & (1<<RXC) ) dummy = UDR;
}
读出UCSRC中的值
unsigned char USART_ReadUCSRC( void )
{
unsigned char ucsrc;
/* 读UCSRC */
ucsrc = UBRRH;
ucsrc = UCSRC;
return ucsrc;
}
问?为什么要加ucsrc = UBRRH;
USART I/O 数据寄存器- UDR
将数据写入UDR 时实际操作的是发送数据缓冲器存器(TXB),读UDR 时实际返回的是接收数据缓冲寄存器(RXB) 的内容。
当数据写入发送缓冲器后,若移位寄存器为空,发送器将把数据加载到发送移位寄存器。然后数据串行地从TxD 引脚输出.
液晶屏
16个引脚
VSS 接地
VDD 接5V正电源
VO 对比度 信号
RS 寄存器选择(数据.指令)
RW
E
D0-D7
BLA
BLK
设置完成之后再开显示
16位中断寄存器TC1
TCNT1是初始值的意思
0CR1A ICR1是TOP值
PD4(0C1B) 连接着灯泡DS142 右下角的灯泡
PD5(OC1A) 连接着灯泡DS141
程序 :通过改变OCR1A的值改变 电压 改变 灯泡的亮暗
void TC1_init(void) //TC1初始化
{
TCCR1A=0xa1; //覆盖PB口的IO功能,并设置为相位修正PWM模式
TCCR1B=0x01; //系统时钟,无分频
TCNT1H=0x00; //初始值
TCNT1L=0x00;
}
int TC1A(int a) //比较A输出函数
{
OCR1A=a;
}
int TC1B(int b) //比较B输出函数
{
OCR1B=b;
}
int main(void)
{
int a,b;
IO_init();
TC1_init();
while(1)
{
for(a=0xffff,b=0x0000;a>0,b<0xffff;a--,b++)
{
TC1A(a);
_delay_ms(20);
TC1B(b);
_delay_ms(20);
}
}
}
达到的效果是/*OCR1A对应渐暗,OCR1B对应渐亮*/
TCCR1A=0xa1; A.B比较匹配时输出低电平
TCCR1B=0x01; 9位相位修正的PWM 计数上限是OX01FF 在0XR1A或0XR1B=TCNT1 是发生匹配置为.
还有一种是捕捉
TC2
只有一个比较通道
普通模式 CTC模式 快速PWM模式
OCR2输出比较寄存器
控制寄存器TCCR2
0C2跟PD7跟蜂宁器连接
程序:
/*蜂鸣器*/
#define F_CPU 7372800UL //定义时钟频率,保证delay函数的准确
#include<avr/io.h>
#include<util/delay.h>
void IO_init() //端口初始化
{
DDRA=0xff;
DDRB=0xff;
DDRC=0xff;
DDRD=0xff;
PORTA=0xff;
PORTB=0xff;
PORTC=0xff;
PORTD=0xff;
}
void TC2_init() //TC2初始化
{
TCNT2=0x00; //计时器
TCCR2=0x6b; //快速PWM模式,16分频
}
void TC2(int a)
{
OCR2=a;
}
int main()
{
int i;
IO_init();
TC2_init();
while(1)
{
for(i=0;i<0xffff;i++)
{
TC2(i);
_delay_ms(10);
}
}
}
改变0CR2的值改变有效电压改变其音量.
总结TC1中的(0C1A 0C1B)分别是PD5 PD4 分别控制DS141 DS142
TC2就是(0C2)就是PD7控制峰宁器.
问:快速PWM模式有比较中断?
ASSR
n -- -- -- AS2 TCN2UB OCR2UB TCR2UB
n 异步TC2 TC2跟新中 输出比较器2跟新中 TC2控制寄存器更新
n
展开阅读全文