打印
[AVR单片机]

请教ATmega16串口收发程序不通

[复制链接]
4306|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ATmega16|  楼主 | 2007-12-21 09:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#define __IN_SERIAL_C__ 
#include "config.h" 

#define BAUDX        8// Baud rate divisor. 
#define BAUD(A) ((F_CPU/BAUDX/(A))-1) 


#define UART_SEND_BUF_SIZE 16            //串口发送缓冲队列大小 
#define UART_RECEIVE_BUF_SIZE 16         //串口接收缓冲队列大小 

static uint8 g_uart_send_buf[UART_SEND_BUF_SIZE];   
static uint8 g_uart_receive_buf[UART_RECEIVE_BUF_SIZE]; 

volatile static uint8 g_uart_send_buf_first_index=UART_SEND_BUF_SIZE-1;  //指向最先进入发送缓冲队列的数据(的前一位) 
volatile static uint8 g_uart_send_buf_last_index=UART_SEND_BUF_SIZE-1;   //指向最后进入发送缓冲队列的数据(的前一位) 

volatile static uint8 g_uart_receive_buf_first_index=UART_RECEIVE_BUF_SIZE-1; //指向最先进入接收缓冲队列的数据(的前一位) 
volatile static uint8 g_uart_receive_buf_last_index=UART_RECEIVE_BUF_SIZE-1;  //指向最后进入接收缓冲队列的数据(的前一位) 


void usart_baud_init(uint16 ubrr ) 

        UBRRH = (uint8_t)(ubrr>>8); 
        UBRRL = ubrr; 
        UCSRA = (BAUDX == 8)?(1<<U2X):0; 
        UCSRB = ((1<<TXEN) | (1<<RXEN));//| (1<<RXCIE)); 
        UCSRC = ((1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0))|_BV(UPM1);//8数据,1停止,偶校验 


void usart_init(void) 

  usart_baud_init(BAUD(9600) ); 




//循环加一,缓冲队列下一个数据的序号 
//return=(val+1)%buf_size 
uint8 inc_cycle(uint8 val,uint8 buf_size) 

  val++; 
 while(val>=buf_size) 
 { 
   val=val-buf_size; 
 } 
  return val; 



//串口数据寄存器空中断 
//如果串口发送队列有数据,发送数据 
//如果没有,关闭发送中断 
SIGNAL(SIG_UART_DATA) 

    UCSRB &= ~_BV(UDRIE);         //关闭发送 
     
    if(g_uart_send_buf_first_index!=g_uart_send_buf_last_index)  //如果发送队列有未发送的数据 
    {       
   g_uart_send_buf_first_index=inc_cycle(g_uart_send_buf_first_index,UART_SEND_BUF_SIZE);//送队列FIRST_INDEX循环加一,指向队列下一个数据 
      UDR =g_uart_send_buf[g_uart_send_buf_first_index]; //读取发送队列数据  
      UCSRB |= _BV(UDRIE);    //打开发送            
   } 


uint8 uart_send_buf_put(data) 
{  
  uint8 temp,inc_cycle_index; 
   
   temp=__save_interrupt();//进入临界段 
   cli(); 
   inc_cycle_index=inc_cycle(g_uart_send_buf_last_index,UART_SEND_BUF_SIZE); 
  if(g_uart_send_buf_first_index!=inc_cycle_index)//如果发送队列数据未满 
  {   
    g_uart_send_buf_last_index=inc_cycle_index;   //发送队列LAST_INDEX循环加一 
    g_uart_send_buf[g_uart_send_buf_last_index]=data;//数据写入发送队列 
     
     __restore_interrupt(temp);   //退出临界段 
     return 1;                    //数据写入发送队列正确返回 
  } 
  else{ 
     __restore_interrupt(temp); //退出临界段 
     
    return 0;                   //数据写入发送队列错误返回 
  } 


//用户API 
//把数据放到串口发送队列 
 uint8 uart_put_char(uint8 data)   

{    uint8 temp;         
         temp=uart_send_buf_put(data);    //数据写入发送队列 
              UCSRB |= _BV(UDRIE);        //打开发送中断 
              return temp;                //返回写入发送队列是否正确 
           


//用户API,阻塞函数 
//连续把ucSize放到串口发送队列 
void uart_block_send_data(uint8 *pucBuffer,uint8 ucSize) 

    uint8 i; 

    for(i = 0; i < ucSize; i++) 
    { 
     while(!uart_put_char(pucBuffer));   //发送连续多发数据,直到全部都正确写入发送队列 
    } 



//串口接收中断 
SIGNAL(SIG_USART_RECV) 
{   
  uint8 data,inc_cycle_index; 
   UCSRB &= ~(1<<RXCIE);        //关闭串口接收 
   data=UDR;                    //读取串口数据寄存器数据 
    inc_cycle_index=inc_cycle(g_uart_receive_buf_last_index,UART_RECEIVE_BUF_SIZE); 
    if(g_uart_receive_buf_first_index!=inc_cycle_index)//如果串口接收队列未满 
    {   
       g_uart_receive_buf_last_index=inc_cycle_index;   //接收队列LAST_INDEX循环加一 

       g_uart_receive_buf[g_uart_receive_buf_last_index]=data;  //数据写入串口接收队列 
   } 
     UCSRB |= (1<<RXCIE); 




//从串口接收队列取出一个数据到pdata[] 
uint8 uart_receive_buf_get(uint8 *pdata) 

   uint8 temp; 
    
   temp=__save_interrupt();//进入临界段 
     cli(); 
 if(g_uart_receive_buf_first_index!=g_uart_receive_buf_last_index)//如果串口接收队列里有数据 
  { 
    g_uart_receive_buf_first_index=inc_cycle(g_uart_receive_buf_first_index,UART_RECEIVE_BUF_SIZE);//串口接收队列FIRST_INDEX循环加1 
     
    *pdata=g_uart_receive_buf[g_uart_receive_buf_first_index];//读取串口接收队列数据 
     
      __restore_interrupt(temp);     //退出临界段 
     return 1;                       //正确取出串口接收数据换回 
  } 
  
  else 
  { 
    __restore_interrupt(temp);       //退出临界段 
    return 0;                       //串口接收队列无数据取出返回 
  } 

  


//用户API,从串口接收队列取出一个数据到pdata[] 
uint8 uart_get_char(uint8 *pdata) 

{      
   return  uart_receive_buf_get(pdata); 



//用户API,阻塞函数 
//连续从串口接收队列取ucSize个数据到pucBuffer[] 
void uart_block_receive_data(uint8  *pucBuffer, uint8 ucSize) 

uint8 i; 

    for(i = 0; i < ucSize; i++) 
    { 
    while(!uart_get_char(&pucBuffer));  //连续接收多个数据,直道全部从接收队列取出 
    } 







我的测试程序,每1/20秒执行一次,用串口调试助手,每秒自动发1个字符,下位机收到后再发给上位机。 
收发一段时间后下位机没有任何返回了。 

      if(uart_get_char(&val1)) 
       { 
        uart_put_char(val1);         
       } 

相关帖子

沙发
NE5532| | 2007-12-21 12:27 | 只看该作者

一个字节能发不?楼主这种期待别人帮调的方法不现实。

使用特权

评论回复
板凳
dcp| | 2007-12-21 13:47 | 只看该作者

先打开串口,main()

main()
{
    puts("OK");  //这样能发出去吗?
}

如果这样串口助手能收到OK再调下去吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

109

主题

229

帖子

0

粉丝