我用ATMega8做个风扇移相调速和周波数调速试验,用INT0检测交流过零,一个LED显示调速的档级,另一个LED显示定时时间的档级。
操作按键用现成任天堂手柄,其内用MC14021并入/串出移位寄存器芯片来并行输入各个键值(0或1),再将结果串行输出到AVR中。
#include<macros.h>
#include <avr/io.h> // 由makefile里定 atmega8
#include "delayM8.h"
#define DDR_SPI DDRB //改用atmega8:
#define DD_MISO 1 //端口PB1输入来自14021的输出(Q8)
#define DD_SCK 5 //端口PB5输出CLK 到14021作移位脉冲
#define DD_CS 2 //端口PB2输出 高低电平 到14021作并行输入操作(高)或移位输出操作(低)
unsigned char key_value;
PORTB = 0xfd;//应先先设电平
DDR_SPI= 0xFd;//再设方向,就不会发生电平瞬间变化 PB1是输入
PORTB=0x00; //端口初始化
unsigned char read_4021(void)
{/*读4021的数据*/
unsigned char i,j;
unsigned char a=0;// 初始值清零 以后遇到某bit为零不再置0
PORTB|=(1<<DD_CS); //并行数据读入,转换使能=1 MC14021当P/S为“1”时,键值并行输入MC14021
asm("nop");
PORTB|=(1<<DD_SCK); //CLK high加在并行输入P1~P8的数据与时钟的上升沿同步地送入寄存器)
MyDelay_us(1); //延时4.25uS
PORTB&=(~(1<<DD_CS)); // pin9=0;//串行移出数据 下降沿 LOAD=0 ;轉成串列資料模式
MyDelay_us(1);
if((PINB & 0x02)==0x02) //读数据线要放到CLK上升沿前面的.因为一开始输出(Q8)有效
a|=1<<(7); //a相应位置1
for(i=1;i<8;i++)
{ PORTB|=(1<<DD_SCK); //pin10=1;//CLK high ,Qn=Qn-1,时钟上升沿开始输出
MyDelay_us(1); //脉冲顶部约4.25-6.5uS左右,延迟函数MyDelay_us(1);
PORTB &=(~(1<<DD_SCK)); //pin10=0;//CLK low ,Qn不变 时钟下降沿输出已经稳定可以读取了
if((PINB & 0x02)==0x02)
a|=1<<(7-i); //a相应位置1,
MyDelay_us(1);
}
return a;
}
void main(void)
{
PORTB = 0xfd;//应先先设电平
DDR_SPI= 0xFd;//再设方向,就不会发生电平瞬间变化 PB1是输入
PORTB=0x00; //端口初始化
....
while(1){
key_value=read_4021(); // 读键盘
//显示函数代码在此。。。
//延迟处理在此。。。
}
}
|