ATmega8A基本编程

有项目用的这款单片机,所以就该单片机基本功能操作做了一个记录。

1:IO操作

 首先初始需要操作的IO,这里主要是配置为输入还是输出,如果是输出设置输出电平。
void port_init(void)
{
	//Run
	DDRC	|= 0x08;   //PC3
	PORTC	|= 0x08;   //set pb1 output high
	//Times
	DDRC	|= 0x04;   //PC2
	PORTC	|= 0x04;   //set pb1 output high  
	//Alarm
	DDRD |= 0x20;   //PD5
	PORTD |= 0x20;   //set pb1 output high
	//Dir485
	DDRD	|= 0x04;   //PD2
	PORTD	&= ~(1 << DIR485);  
	//PORT_DIR485	|= (1 << DIR485); 
	UCSRA |= (1 << TXC);
	
	//PLUS
	DDRD	|= 0x80;   //PD7
	PORTD	&= ~(1 << PLUS);
	
	//DDRC	&= 0xFE;   //PC0
	//PORTC	|= 0x01;	
}

然后就是在主循环中设置或者读取值。设置时,用PORT的定义,读取是用PIN的定义。

2:定时器

void timer0_init(void)
{
   TCCR0 = 0x00;     //timer0 普通模式
   TCCR0 = 0x03;     //预分频/64 启动TIME0 普通模式
   TCNT0 = 141;      //晶振8MHz, 频率为1KHz 0x83 = 256 - 8000000 / 64 / 1000 
					 //晶振7MHz, 频率为1KHz  141 = 256 - 7372800 / 64 / 1000  
   TIMSK|=0x01; 
   TIFR |= (1<<TOV0);
   //SREG|=0x80;      //使能全局中断
}

在主程序中
timer0_init();
sei(); //使能总中断

在中断程序中
ISR(TIMER0_OVF_vect){
	TCNT0 = 141;           //重装
	t_1s++;
	if(t_1s <= 800)   //1s到
	{
	 	PORT_RUN |= (1<<RUN);       //pd1输出高定平 	
	}
 	else
    {
  		PORT_RUN &= ~(1<<RUN);       //pd1输出低电平	
 	}
	if(t_1s >= 1000)
	{
		t_1s = 0;
	}
}
其中PORT_RUN和RUN定义如下
#define PORT_RUN PORTC
#define RUN 3

3:AD操作

AD定义为轮询采样

void Ad_init(){
	//ADCSRA = 0x00;
	//ACSR = 0x80;
	ADMUX=0X40;//外部参考电压,右对齐,0通道
	//ADCSRA = 0xE4;
	//ADCSRA =_BV(ADEN);//使能ADC,单次转换模式
	//AD使能, 启动,连续转换,32分频, 7372800 / 64 = 115.2khz
	//ADCSRA =_BV(ADEN) + _BV(ADSC) + _BV(ADFR) + _BV(ADIE) + 0x06;
	//ADCSRA =_BV(ADEN) + _BV(ADSC) + _BV(ADFR) + 0x06;
}
U16 Ad_Convert(void){
	//ADMUX=0Xc0;//内部2.56V参考电压,0通道
	//ADMUX=0X00;//外部参考电压,右对齐,0通道
	ADCSRA =_BV(ADEN) + 0x06;//使能ADC,单次转换模式	
	ADCSRA |=_BV(ADSC);
	//while(ADCSRA & (1 << ADSC));
	while(!(ADCSRA & (1 << ADIF)));
	addata = ADCL;       //ADCL must be read first, then ADCH.
	addata += (ADCH<<8);	
	ADCSRA = 0 + (1 << ADIF);//关闭ADC
	//ADCSRA &= ~(_BV(ADIF));
	return 0;
}

需要注意的是读取AD转换结果是,需要先度低字节在读高直接。

4:串口通信

串口通信,发送用轮询方式,接收用中断方式,因为串口为485线路,所以有个485方向选择设置,这个设置的时间点比较关键。
U8 recv;
U8 send;
U8 recv_buff[RECV_LENGTH];
U8 send_buff[SEND_LENGTH] = {0x7E, 0x00, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7e};
//串口收发状态,0:等待接收,1:接收中,2:接收完成,待处理,3,待回复。
U16 recv_flag = 0;
U16 send_flag = 0;
//收发延迟
U16 recv_delay = 0;
U16 send_delay = 0;
//收发数据长度
U16 recv_length = 0;
U16 send_length = 0;

void Serial_init(){
	UBRRH=(U8)((UBRR_PARAM) >> 8);
	UBRRL=(U8)UBRR_PARAM;
	
	UCSRB|=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
	/* Enable receiver and transmitter */
	//UCSRB = (1<<RXEN)|(1<<TXEN);
	/* Set frame format: 8data, 2stop bit */
	//UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
	UCSRC = (1<<URSEL)|(3<<UCSZ0);
}

void Serial_SendChar(char data)
{
	PORT_DIR485	|= (1 << DIR485);
	//UCSRA |= (1 << TXC);
	//查询方式发送
	while(!(UCSRA & (1 << UDRE)));
	UDR = data;
	while(!(UCSRA & (1 << TXC)));
	UCSRA |= (1 << TXC);
	PORT_DIR485	&= ~(1 << DIR485);
}
void Serial_SendArry(U8 *data, int len)
{
	int i= 0;
	PORT_DIR485	|= (1 << DIR485);
	//UCSRA |= (1 << TXC);
	//查询方式发送
	for(; i< len; i++){
		while(!(UCSRA & (1 << UDRE)));
		UDR = data[i];
	}
	while(!(UCSRA & (1 << TXC)));
	UCSRA |= (1 << TXC);
	PORT_DIR485	&= ~(1 << DIR485);
}

/************************************************************************/
/* 串口接收中断                                                          */
/************************************************************************/
ISR(USART_RXC_vect){
	recv = UDR;
	switch(recv_flag)
	{
		case 0:
		recv_overtime:
		if(recv == 0x7E){
			recv_delay = RECV_DELAY;
			recv_flag = 1;
			recv_length = 0;
			recv_buff[recv_length]=recv;
			recv_length ++;
		}
		break;
		case 1:
		if(RECV_DELAY == 0){
			recv_flag = 0;
			goto recv_overtime;
		}
		recv_delay = RECV_DELAY;
		recv_buff[recv_length]=recv;
		recv_length ++;
		if(recv_length == 6){
			if(recv == 0x7E){
				recv_flag = 2;
				}else{
				recv_flag = 0;
			}
		}
		break;
		default:
		break;
	}
}

5:EEProm操作

int EEProm_write_byte(U16 addr, U8 data){
	while(EECR & (1<<EEWE)); /* 等待上一次写操作结束 */
	EEAR = addr; /* 设置地址和数据寄存器*/
	EEDR = data;
	//cli();
	EECR |= (1<<EEMWE); /* 置位EEMWE */
	EECR |= (1<<EEWE); /* 置位EEWE 以启动写操作*/
	//sei();
	return 0;
};
//从EEProm的0地址处读取一字节赋给ram变量temp
U8 EEProm_read_byte(U16 addr){
	while(EECR & (1<<EEWE)); /* 等待上一次写操作结束 */
	EEAR = addr; /* 设置地址寄存器*/
	EECR |= (1<<EERE); /* 设置EERE 以启动读操作*/
	return EEDR; /* 自数据寄存器返回数据 */
}

int EEProm_write_arry(U16 addr, U8 *data, U16 len){
	int i = 0;
	for(; i< len; i++){
		while(EECR & (1<<EEWE)); /* 等待上一次写操作结束 */
		EEAR = addr + i; /* 设置地址和数据寄存器*/
		EEDR = *(data + i);
		EECR |= (1<<EEMWE); /* 置位EEMWE */
		EECR |= (1<<EEWE); /* 置位EEWE 以启动写操作*/
	}	
	return 0;	
};
//从EEProm的0地址处读取一字节赋给ram变量temp
int EEProm_read_arry(U16 addr, U8 *data, U16 len){
	int i = 0;
	for(; i< len; i++){
		while(EECR & (1<<EEWE)); /* 等待上一次写操作结束 */
		EEAR = addr + i; /* 设置地址寄存器*/
		EECR |= (1<<EERE); /* 设置EERE 以启动读操作*/
		*(data + i) = EEDR;
	}
	return 0; 
}

结束

上述代码经验证能正常运行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cetclyb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值