搜索
bottom↓
回复: 6

在WinAVR上使用printf原来这么简单,加了缓冲区用中断发送,请大家帮忙看看,拍砖别拍脸

[复制链接]

出0入0汤圆

发表于 2011-12-7 10:04:37 | 显示全部楼层 |阅读模式
调试程序的时候对于没有仿真器的朋友来说,使用串口是一个很好的方法(个人觉得),而使用printf这个函数会更加方便。

              看了下WinAVR的手册,然后自己改写了一下,已经能实现printf函数的功能了,自己了加入了缓冲区。


/******************************************************************************************************************/
#ifndef __AVR_CPU_H__
#define __AVR_CPU_H__

#include "avr/io.h"
#include "avr/interrupt.h"
#include "util/delay.h"
#include "avr/pgmspace.h"

#ifndef F_AVR_CPU
#define F_AVR_CPU 11059200UL        //使用的晶振频率
#endif

typedef signed   char  int8s;       
typedef unsigned char  int8u;
typedef signed   short int16s;
typedef unsigned short int16u;
typedef signed   long  int32s;
typedef unsigned long  int32u;

#define SET_BIT( VAL,BIT )      ( VAL |= _BV(BIT) )
#define CLR_BIT( VAL,BIT )      ( VAL &= ~_BV(BIT) )

#ifndef NOP
#define NOP  __asm("nop\n")
#endif

#endif

/********************************************************************************************************************/

#ifndef __USART_H__
#define __USART_H__

#include "avr_cpu.h"
#include <stdio.h>

extern void Printf_Init( void );

#endif

/********************************************************************************************************************/

#include "usart.h"

#define USART0_BAUDRATE         9600UL  //波特率
#define USART0_TX0_BUFFER_SIZE        64      //缓冲区大小

static int  uart_putchar( char c, FILE *stream );               //使用printf需要的
static FILE mystdout = FDEV_SETUP_STREAM( uart_putchar, NULL,   //使用printf需要的
                                          _FDEV_SETUP_WRITE );
static void Usart0_Init( void );           //串口0初始化
static void Usart0_Buffer_Init( void );           //串口0发送缓冲区初始化

volatile static unsigned char usart0_tx0_buffer[USART0_TX0_BUFFER_SIZE];   //定义缓冲区
volatile static unsigned char usart0_tx0_cnt;       //有效数据的个数
volatile static unsigned char usart0_tx0_header;    //头
volatile static unsigned char usart0_tx0_trail;     //尾

//初始化printf
void Printf_Init( void )
{
     Usart0_Buffer_Init( );
     Usart0_Init( );
     stdout = &mystdout;       
}
//使用printf需要的,这里把要发送的数据放入发送缓冲区并发送出去
int uart_putchar( char c, FILE *stream )
{
        if ( c == '\n' )
        {
             uart_putchar( '\r', stream );       
        }       
       
        while( usart0_tx0_cnt == USART0_TX0_BUFFER_SIZE )
        {
             //如果缓冲区溢出,则在这里等待       
        }
       
        usart0_tx0_buffer[usart0_tx0_header] = c;
        usart0_tx0_header++;
       
        if ( usart0_tx0_header >= USART0_TX0_BUFFER_SIZE )
        {
              usart0_tx0_header = 0;       
         }
       
        cli();
        if ( usart0_tx0_cnt == 0 )
        {
              UDR0 = usart0_tx0_buffer[usart0_tx0_trail];       
        }
        usart0_tx0_cnt++;
        sei();
       
        return 0;
}
//串口0初始化,发送暂时不接收,8位数据,1个停止位,9600波特率
static void Usart0_Init( void )
{
        UCSR0A  =  0x00;
        UCSR0B  =  ( 1<<TXCIE )|( 1<<TXEN );
        UCSR0C  =  ( 1<<UCSZ1 )|( 1<<UCSZ0 );
        UBRR0H  =  (int8u)(F_AVR_CPU/(16*USART0_BAUDRATE)-1)/256;
        UBRR0L  =  (int8u)(F_AVR_CPU/(16*USART0_BAUDRATE)-1)%256;       
}
//初始化缓冲区数据
static void Usart0_Buffer_Init( void )
{
       int8u i;
       
       for ( i = 0; i < USART0_TX0_BUFFER_SIZE; i++ )
       {
            usart0_tx0_buffer = 0;       
       }       
       
       usart0_tx0_cnt    = 0;
       usart0_tx0_header = 0;
       usart0_tx0_trail  = 0;
}
//串口0发送中断服务程序
ISR( USART0_TX_vect )
{
      if ( --usart0_tx0_cnt )
      {
            usart0_tx0_trail++;
               
            if ( usart0_tx0_trail >= USART0_TX0_BUFFER_SIZE )
            {
                  usart0_tx0_trail = 0;       
            }       
       
            UDR0 = usart0_tx0_buffer[usart0_tx0_trail];
      }
      else
      {
            usart0_tx0_trail = usart0_tx0_header;       
      }
}

在主程序中

        int temp=1234;
        printf( "The test value is %d", temp );



(原文件名:usart.jpg)

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2011-12-7 10:20:13 | 显示全部楼层
能使用scanf吗?

出0入0汤圆

发表于 2011-12-7 10:25:00 | 显示全部楼层
回复【1楼】alasika  绿
-----------------------------------------------------------------------

可以设置使用的

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=664416

不过太耗资源,还是自己实现的好

出0入0汤圆

发表于 2011-12-7 10:30:06 | 显示全部楼层
以前使用AVR的时候也这么使用过,感觉还是非常方便的。

出0入0汤圆

 楼主| 发表于 2011-12-7 10:51:03 | 显示全部楼层
回复【1楼】alasika  绿
-----------------------------------------------------------------------

  可以,但是感觉没有printf好用(应该是我不会用)

出0入0汤圆

 楼主| 发表于 2011-12-7 10:52:23 | 显示全部楼层
回复【2楼】kvs112219  
-----------------------------------------------------------------------

       特别是手头上没有仿真器,比弄块屏来显示好多了

出0入0汤圆

 楼主| 发表于 2011-12-7 11:03:38 | 显示全部楼层
刚刚试了一下,在WinAVR中printf还可以使用__FUNCTION__   __LINE__
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 07:13

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表