这几天刚从51转到AVR还有很多东西不太熟悉,现在用的是mega8515,今天调试串口,都快把我弄崩溃了,开始是能接收不能 发送,到后来是能发送不能接收,再到后为是不能发送比拟能接收……真快把我弄死了,后来再看看寄存器,再看看程序,还是程序的问题,下面是俺开始写的程序:
//ICC-AVR application builder : 2009-11-24 14:09:56
// Target : M8515
// Crystal: 8.0000Mhz
#include <iom8515v.h>
#include <macros.h>
#define Setbit(REG,N) REG|=(1<<N) //对REG的N位置1
#define Clrbit(REG,N) REG&=~(1<<N) //对REG的N位清零
#define Invbit(REG,N) REG^=(1<<N) //对REG的N位取反
/*_*=============ID指示灯亮/灭宏定义==================*_*/
#define Led_on() Clrbit(PORTD,7)
#define Led_off() Setbit(PORTD,7)
/*>>>>>>>>>>>>>>>>>>>>>>发送使能、发送关闭宏定义<<<<<<<<<<<<<<<<<<<<<*/
#define Send_on() Setbit(PORTD,2)
#define Send_off() Clrbit(PORTD,2)
typedef unsigned char uint8; /* 定义可移植的无符号8位整数关键字*/
typedef signed char int8; /* 定义可移植的有符号8位整数关键字*/
typedef unsigned int uint16; /* 定义可移植的无符号16位整数关键字*/
typedef signed int int16; /* 定义可移植的有符号16位整数关键字*/
typedef unsigned long uint32; /* 定义可移植的无符号32位整数关键字*/
typedef signed long int32; /* 定义可移植的有符号32位整数关键字*/
void port_init(void)
{
PORTA = 0xff; //初始状态为高电平,为读取设备ID号做准备
DDRA = 0x00; //A口做为输入口,用来读取编码开关的值
PORTB = 0x00; //B口做为输出口,通过2803来控制继电器
DDRB = 0xFF;
PORTD = 0x80; //初始状态时灯灭
DDRD = 0x84; //PD2控制485芯片的使能端,PD7控制指示灯
}
/**************************************************************/
//UART0 initialize串口初始化
// desired baud rate: 38400
// actual: baud rate:38462 (0.2%)
/*************************************************************/
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC =(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//0x46;// BIT(URSEL) | 0x06;//异步、无校验、9位数据位
UBRRL = 0x0C; //UBRRL=(Fosc/16/(Baud+1))%256; set baud rate lo
UBRRH = 0x00; //UBRRH=(Fosc/16(Baud+1))/256; set baud rate hi
UCSRB |=/*(1<<RXCIE)|(1<<RXEN)/*|(1<<TXEN)*/(1<<UCSZ2);//0x94;先关闭发送使能
}
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts (关中断)
port_init();
uart0_init();
MCUCR = 0x00;
EMCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00;
SEI(); //re-enable interrupts (开中断)
//all peripherals are now initialized
}
/*=====================================================*/
void Delay_100us(uint16 t) //100us
{
uint8 i;
while((t--)>0)
{
for(i=0;i<12;i++);
}
}
void Delay_1ms(void) //1ms
{
uint16 i;
for(i=1;i,(uint16)(8*143-2);i++);
}
void Delay_ms(uint16 tt)//tt ms
{
uint8 i;
while(i<tt)
{
Delay_1ms();
i++;
}
}
void Usart_transmit(uint16 data)
{
//UCSRB|=BIT(3);//开启发送使能
while(!(UCSRA&(1<<UDRE)));
//Send_on();
/*******将第九位数复制到TXB8*********/
//while(UCSRB&(~BIT(3)));//等待发送使能
UCSRB&=~(1<<TXB8); //发送的第九位数据一直是0
//if(data&0x0100)
//UCSRB|=(1<<TXB8);
UDR=data;
while(!(UCSRA&(1<<TXC)));
//UCSRC|=(1<<TXC);
//Send_off();
UCSRB&=~BIT(3);//发送使能关闭
}
void main(void)
{
uint8 i;
init_devices();
//Send_on();
PORTD|=BIT(2); //485发送使 能
UCSRB|=BIT(3);//发送使能关
while(1)
{
Led_on();
//for(i=0;i<10;i++)
//{
PORTC="0X58"; //TEST
Usart_transmit(0x58); //发送数据
//Delay_ms(100);
//Led_off();
//}
//UCSRB&=~BIT(3);//发送使能关闭
//PORTD&=~BIT(2); //485发送关闭
//PORTC=0X58; //TEST
Led_off();
}
}
当时我只是查询接收,但接收完了,灯不会灭,也就是程序执行到 Usart_transmit(0x58); //发送数据 ;就不往下执行了,真弄不明白到底是怎么回事?
……
……
……
经过若干小时的奋斗,现在终于弄出了点眉目,原来是
PORTC=0X58; //TEST
Usart_transmit(0x58); //发送数据
这两句话是不能话在while(1)这个死循环中的,不然程序一直在执行这个死循环,当然就是连续发数据了,应该在这里面写几个条件语句限制才行
例如:
if(flag==1)
{
PORTB=0xff;
Usart_transmit(Dat);
Delay_ms(5000);
Led_off();
//flag=0;
}
else{Led_on();PORTB=Dat;}
这样的话就不会连续发数据了
不过还是有些其它的问题,只有再看看程序再说了,呵呵,不过终于看到希望了^_^
下面是俺现在的程序:
/*===========================================================================*/
// ICC-AVR application builder : 2009-11-6
// Target : M8515
// Crystal: 8.0000Mhz
// Author: Citect Xu
/*==========================================================================*/
#include <iom8515v.h>
#include <macros.h>
#include<stdio.h>
#define Setbit(REG,N) REG|=(1<<N) //对REG的N位置1
#define Clrbit(REG,N) REG&=~(1<<N) //对REG的N位清零
#define Invbit(REG,N) REG^=(1<<N) //对REG的N位取反
/*_*==================ID指示灯亮/灭宏定义=============*_*/
#define Led_on() Clrbit(PORTD,7)
#define Led_off() Setbit(PORTD,7)
/*>>>>>>>>>>>>>>>>>>>>>>发送使能、发送关闭宏定义<<<<<<<<<<<<<<<<<<<<<*/
//Send_on()是485发送使能;Send_off()是485发送关闭
//TX_EN()是单片机串口发送使能;RX_EN()是单片机串口发送关闭
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>^_^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
#define Send_on() Setbit(PORTD,2)
#define Send_off() Clrbit(PORTD,2)
#define TX_EN() UCSRB|=BIT(3)
#define RX_EN() UCSRB&=~BIT(3)
typedef unsigned char uint8; /* 定义可移植的无符号8位整数关键字*/
typedef signed char int8; /* 定义可移植的有符号8位整数关键字*/
typedef unsigned int uint16; /* 定义可移植的无符号16位整数关键字*/
typedef signed int int16; /* 定义可移植的有符号16位整数关键字*/
typedef unsigned long uint32; /* 定义可移植的无符号32位整数关键字*/
typedef signed long int32; /* 定义可移植的有符号32位整数关键字*/
void port_init(void)
{
PORTA = 0xff; //初始状态为高电平,为读取设备ID号做准备
DDRA = 0x00; //A口做为输入口,用来读取编码开关的值
PORTB = 0x00; //B口做为输出口,通过2803来控制继电器
DDRB = 0xFF;
PORTD = 0x80; //初始状态时灯灭
DDRD = 0x84; //PD2控制485芯片的使能端,PD7控制指示灯
}
/**************************************************************/
//UART0 initialize串口初始化
// desired baud rate: 38400
// actual: baud rate:38462 (0.2%)
/*************************************************************/
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC =(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//0x46;// BIT(URSEL) | 0x06;//异步、无校验、9位数据位
UBRRL = 0x0C; //UBRRL=(Fosc/16/(Baud+1))%256; set baud rate lo
UBRRH = 0x00; //UBRRH=(Fosc/16(Baud+1))/256; set baud rate hi
UCSRB=(1<<RXCIE)|(1<<RXEN)/*|(1<<TXEN)*/|(1<<UCSZ2);//0x94;先关闭发送使能
}
void init_devices(void)
{
CLI(); //disable all interrupts (关中断)
port_init();
uart0_init();
MCUCR = 0x00;
EMCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00;
SEI(); //re-enable interrupts (开中断)
}
/*=====================================================*/
void Delay_100us(uint16 t) //100us
{
uint8 i;
while((t--)>0)
{
for(i=0;i<12;i++);
}
}
void Delay_1ms(void) //1ms
{
uint16 i;
for(i=1;i,(uint16)(8*143-2);i++);
}
void Delay_ms(uint16 tt)//tt ms
{
uint8 i;
while(i<tt)
{
Delay_1ms();
i++;
}
}
uint8 Receive_buf[6];
uint8 R_count=0;
uint8 Dat;
uint8 flag="0";
#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
/***********************************************************/
//uart has received a character in UDR
//USART接收中断,接收一个字符
/**********************************************************/
void uart0_rx_isr(void)
{
CLI();
if(UCSRB&(1<<RXB8))
{
Dat="UDR";
if(Dat==0xff)
{flag=1;}
else {flag=0;}
/*Receive_buf[R_count++]=UDR;
if(R_count==6)
{R_count=0;}
UDR="0X00";*/
}
else {
Dat="0";
/* uint8 i;
for(i=0;i<6;i++)
{
Receive_buf=0;
} */
}
SEI();
}
void Usart_transmit(uint8 data)
{
Send_on();//开启485发送使能
TX_EN(); //开启串口发送使能
while(!(UCSRA&(1<<UDRE)));
//Send_on();
/*******将第九位数复制到TXB8*********/
//while(UCSRB&(~BIT(3)));//等待发送使能
UCSRB&=~(1<<TXB8); //发送的第九位数据一直是0
//if(data&0x0100)
//UCSRB|=(1<<TXB8);
UDR=data;
while(!(UCSRA&(1<<TXC)));
//UCSRC|=(1<<TXC);
Send_off();
UCSRB&=~BIT(3);//发送使能关闭
}
void main(void)
{
uint8 i;
init_devices();
//Send_on();
//PORTD|=BIT(2); //485发送使 能
//UCSRB|=BIT(3);//发送使能关
//PORTB=0X01;
while(1)
{
if(flag==1)
{
PORTB="0xff";
Usart_transmit(Dat);
Delay_ms(5000);
Led_off();
//flag=0;
}
else{Led_on();PORTB=Dat;}
/*if(Receive_buf[0]=0xff)
{
Led_on();
PORTB="Receive"_buf[0]; //TEST
UCSRB|=BIT(3);//发送使能关
Usart_transmit(Receive_buf[0]); //发送数据
Delay_ms(500);
Led_off();
}*/
}
}
不过现在还是有问题,就是:
在主程序中
if(flag==1)
{
PORTB="0xff";B口给高电平
Usart_transmit(Dat); //发送Dat
Delay_ms(5000);//延时5S
Led_off();//灯关
}
这两句没有好好执行,在实验中发现当我发送0xff时,PORTB口确实是高了一下,而灯也只是闪了一下,为什么没有停在这个状态呢?
这一情况还没有想明白,还得好好检查一下程序,也得好好理一下思路才行,不然钻进死胡同就完蛋了,不管怎么说吧,俺还是看到了希望的曙光!
不知道在这里能不能遇到什么大虾什么的前辈否,要是有缘遇到希望能帮俺看一下,谢谢!俺的QQ是515673876;俺的邮箱是:xucun915@126.com
用户181767 2010-1-4 21:35