📄 main._c
字号:
//ICC-AVR application builder : 2007-2-22 12:20:11
// Target : M16
// Crystal: 10.000Mhz
#include <iom16v.h>
#include <macros.h>
unsigned char tmp_cn_0; //临时计数器——0
unsigned char tmp_cn_1; //临时计数器——1
unsigned char led_ch=0x80; //闪烁的花样
unsigned char key_code; //键盘按下的键盘代码
unsigned char tmp_led_index=0x00;
unsigned char const LED_INDEX[]={0X3F,0X06,0X5B,0X4F,
0X66,0X6D,0X7D,0X07,
0X7F,0X6F};//共阴管的数字0-9的代码
void port_init(void)
{
PORTA = 0xC0;
DDRA = 0xC0; //高2位作为10位ADC的MSB,低2位用外部ADC输入,其余用于键盘的输入
PORTB = 0xFF;
DDRB = 0xFF; //驱动静态595显示,只用到高4位,低四位保留
PORTC = 0xFF; //m103 output only
DDRC = 0xFF; //ADC的低8位输出
PORTD = 0xFF;
DDRD = 0xFF; //高6位用于显示LED,低2位用于串口的输出。
}
//TIMER0 initialize - prescale:256
// WGM: Normal
// desired value: 2mSec
// actual value: 1.997mSec (0.2%)
void timer0_init(void) //硬件计数器0的初始化程序
{
TCCR0 = 0x00; //stop
TCNT0 = 0xB2; //set count
OCR0 = 0x4E; //set compare
TCCR0 = 0x04; //start timer
}
/*-----------------------ADC转换初始化----------------------------------------*/
//ADC initialize
// Conversion time: 26uS
void adc_init(void)
{
ADCSR = 0x00; //disable adc
ADMUX = 0x00; //选择外部基准电压 通道 0 输入
ACSR = 0xC0; //模拟比较器控制和状态寄存器 ACSR
//ACD置1,使模拟比较器禁用
/*--ACD--ACBG--ACO--ACI---ACIE---ACIC---ACIS1---ACIS0------------------------*/
/*-模拟比较起禁用--模拟比较器的能隙基准源--模拟比较起输出--模拟比较器中断标志*/
/*-模拟比较器中断使能--模拟比较器输入捕捉使能--模拟比较器中断模式选择--------*/
ADCSR = 0x8B;//模拟比较起控制和状态寄存器
/*-----------ADEN---ADSC---ADFR---ADIF---ADIE---ADPS2---ADPS1---ADPS0--------*/
//使能模数转换 ADC开始转换 ADC连续转换 ADC中断使能 128分频
}
/*-----------------------ADC转换中断程序--------------------------------------*/
#pragma interrupt_handler adc_isr:15
void adc_isr(void) //组合输出ADC DATA
{
unsigned char rr=0;
//conversion complete, read value (int) using...
PORTC=~(ADCL); //c口显示低8位的信息 (反相)
rr =ADCH<<6; //高8位的信息
rr ^=(0x03<<6); //反相
PORTA=rr; //在A口高2位显示
}
void start_adc_0(void) //启动ADC转换的程序
{
ADMUX = 0x00; //选择通道0
ADCSR |= 0x40; //开始ADC转换
}
//SPI initialize //初始化硬件SPIS口的程序
// clock rate: 2500000hz
void spi_init(void)
{
SPCR = 0x50; //setup SPI
SPSR = 0x00; //setup SPI
}
void SPI_595_Out(unsigned char i) //HC595数据的输出
{
SPDR = i; /* 启动数据传输 */
while (!(SPSR & (1<<SPIF))); //等待传输结束
}
void disp_led(unsigned char i)
{
PORTB &= ~(1 << PB4); //准备锁存,在全部的四个LED数据送完后再锁存
SPI_595_Out(i);
PORTB |= (1 << PB4); //在这个时候锁存数据 显示
}
//UART0 initialize //初始化串口0的程序
// desired baud rate: 9600
// actual: baud rate:9615 (0.2%)
// char size: 8 bit 没有校验位
// parity: Disabled
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = BIT(URSEL) | 0x06;
UBRRL = 0x40; //set baud rate lo
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x98;
}
void USART_Transmit( unsigned char data )
{
while ( !( UCSRA & (1<<UDRE)) ) // 等待发送缓冲器为空
;
UDR = data; //将数据放入缓冲器,发送数据
}
unsigned char USART_Receive(void) //使用中断接受时不用此函数
{
while ( !(UCSRA & (1<<RXC)) ) // 等待接收数据
;
return UDR; // 从缓冲器中获取并返回数据
}
#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr(void) //串口0的中断服务程序
{
USART_Transmit(UDR); //把接收到的数据重新发回给PC机
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer0_init();
uart0_init();
spi_init();
adc_init();
MCUCR = 0x00;
GICR = 0x00;
ASSR &= ~(0X08);
TIMSK = 0x01; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void flash_led_type1(void) //PD口的跑马灯显示 从右到左
{
if (led_ch==0x02) led_ch=0x80;
PORTD=~(led_ch);
led_ch=led_ch>>1;
}
void flash_led_type2(void) //PD口的跑马灯显示 从左到右
{
if (led_ch==0x00) led_ch=0x02;
PORTD=~(led_ch);
led_ch=led_ch<<1;
}
void flash_led_type3(void) //PD口的跑马灯显示 反相
{
PORTD^=0XFC;
}
void flash_led_type4(void) //PD口的跑马灯显示 流水
{
unsigned char tmp_PD;
tmp_PD=PIND;
tmp_PD|=0XFC;
led_ch++;
if (led_ch==0X87) led_ch=0X80;
switch (led_ch)
{
//case 0X81: PORTD=tmp_PD&(~(0X78)); break; //0111 10 00 代码
//case 0X82: PORTD=tmp_PD&(~(0XD4)); break; //1011 01 00 代码
//case 0X83: PORTD=tmp_PD&(~(0XCC)); break; //1100 11 00 代码
//case 0X84: PORTD=tmp_PD&(~(0XCC)); break; //1100 11 00 代码
//case 0X85: PORTD=tmp_PD&(~(0XD4)); break; //1011 01 00 代码
//case 0X86: PORTD=tmp_PD&(~(0X78)); break; //0111 10 00 代码
case 0X81: PORTD=~(0X78); break; //0111 10 00 代码
case 0X82: PORTD=~(0XD4); break; //1011 01 00 代码
case 0X83: PORTD=~(0XCC); break; //1100 11 00 代码
case 0X84: PORTD=~(0XCC); break; //1100 11 00 代码
case 0X85: PORTD=~(0XD4); break; //1011 01 00 代码
case 0X86: PORTD=~(0X78); break; //0111 10 00 代码
}
}
void delay30ms(void) //延时30毫秒的子程序
{
unsigned int tmp_delay_cn;
for (tmp_delay_cn=0;tmp_delay_cn<300;tmp_delay_cn++)
;
}
unsigned char check_key_pressed(void) //检查是否有键盘按下
{
unsigned char key_tem;
key_tem=PINA &= ~(0XC3);
if(key_tem!=0X3C)
return 1;
else
return 0;
}
unsigned char find_key_code(void)
{
unsigned char uuu;
if(check_key_pressed()==1)
{
delay30ms(); //延时去抖动
if(check_key_pressed()==1)
{
uuu=(PINA & 0X3C);
return uuu; //屏蔽最高和最低两位
}
}
return 0XC3;
}
#pragma interrupt_handler timer0_ovf_isr:10 //
void timer0_ovf_isr(void)
{
TCNT0 = 0xB2; //计数器初始值重载
if (tmp_cn_0==100) //固定时间产生变化
{
switch (key_code) //根据按下的键盘产生一定的闪灯花样
{
case 0X1C: flash_led_type4(); break;
case 0X2c: flash_led_type3(); break;
case 0X34: flash_led_type2(); break;
case 0X38: flash_led_type1(); break;
default: flash_led_type4(); break;
}
disp_led(LED_INDEX[tmp_led_index]); //循环显示8段数字LED
tmp_led_index++;
if (tmp_led_index==10) tmp_led_index=0; //LED计数器归零
tmp_cn_0=0; //临时计数器0归零
}
else
{
tmp_cn_0=tmp_cn_0+1; //临时计数器递增
}
}
//****************** MAIN 程序的入口*************************//
void main()
{
unsigned char tmp_key_code;
init_devices();
while(1)
{
start_adc_0(); //循环进行ADC转换
tmp_key_code=find_key_code() & 0X3C; //判断是否按下键盘
if (tmp_key_code!=0x3c) key_code=tmp_key_code;
}
}
//****************** MAIN 程序结束 *************************//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -