有项目用的这款单片机,所以就该单片机基本功能操作做了一个记录。
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;
}
结束
上述代码经验证能正常运行