ARM 系列 -- FS2410 开发板上通过串口实现 printf

发布者:Shuangfei最新更新时间:2016-12-02 来源: eefocus关键字:FS2410  串口实现  printf 手机看文章 扫描二维码
随时随地手机看文章

一、目的
   到目前为止我们所编写的程序都是直接烧到裸板(FS2410)上运行,没有借助操作系统,如果哪个环节出错了,就只能揣测代码的逻辑,无法借助 GDB 调试,这无形增加了编写代码的难度,如果任意时刻我们能把某个变量的值打印出来多好啊...呵呵, 你也许有同样的困惑,上一个实验我们对 UART 串口编程实现了对超级终端接收和发送数据,也许我们可以编写一个类似 C 语言里的 printf,作用就是向上位机的超级终端发送我们指定的任何数据。怀着这样美好的愿望,随我一起踏上征程吧。

二、代码
   很多代码是在前面几个实验的基础上进行整理复用之,更多细节请参考前面随笔,这里
仅附简略注解。
   
   @ 文件 head.s
   @ 作用:关闭看门狗、SDRAM 的初始化设置、搬移 Nand Flash 4K 以后
   @ 的代码到 SDRAM 的指定位置、执行 SDRAM 中的代码
   .text
   .global _start
   _start:
    ldr r0, =0x53000000 @ Close Watch Dog Timer
    mov r1, #0x0
    str r1, [r0]
   
    bl  memory_setup @ Initialize memory setting
    bl  flash_to_sdram @ Copy code to sdram
    
        ldr sp, =0x34000000 @ Set stack pointer
    ldr pc, =main           @ execute the code in SDRAM


   @ 文件 mem.s
   @ 作用:SDRAM 的初始化设置 
   @ 关于初始化的更多细节,请参考我前面的随笔
   .global memory_setup
   memory_setup:
    mov  r1, #0x48000000
    adrl r2, mem_cfg_val
    add  r3, r1, #13*4
   1: 
    @ write initial values to registers
    ldr  r4, [r2], #4
    str  r4, [r1], #4
    cmp  r1, r3
    bne  1b
    mov  pc, lr
    
    .align 4
   mem_cfg_val:
    .long 0x22111110 @ BWSCON
    .long 0x00000700 @ BANKCON0
    .long 0x00000700 @ BANKCON1
    .long 0x00000700 @ BANKCON2
    .long 0x00000700 @ BANKCON3
    .long 0x00000700 @ BANKCON4
    .long 0x00000700 @ BANKCON5
    .long 0x00018005 @ BANKCON6
    .long 0x00018005 @ BANKCON7 9bit
    .long 0x008e07a3 @ REFRESH
    .long 0x000000b2 @ BANKSIZE 
    .long 0x00000030 @ MRSRB6
    .long 0x00000030 @ MRSRB7


   @ 文件 flash.s
   @ 作用:设置 Nand Flash 的控制寄存器、读取 Nand Flash
   @ 中的代码到 SDRAM 的指定位置,更多细节请参考我前面的随笔
   .equ NFCONF, 0x4e000000 
   .equ NFCMD,  0x4e000004 
   .equ NFADDR, 0x4e000008 
   .equ NFDATA, 0x4e00000c 
   .equ NFSTAT, 0x4e000010 
   .equ NFECC,  0x4e000014
   .global flash_to_sdram 
   flash_to_sdram:
        @ Save return addr
        mov r10,lr
    
        @ Initialize Nand Flash
        mov r0,#NFCONF
        ldr r1,=0xf830 
        str r1,[r0] 
    
        @ First reset and enable Nand Flash
        ldr r1,[r0] 
        bic r1, r1, #0x800 
        str r1,[r0] 
    
        ldr r2,=NFCMD
        mov r3,#0xff 
        str r3,[r2]
    
        @ for delay
        mov r3, #0x0a 
   1: 
        subs r3, r3, #1 
        bne 1b 
   
   @ Wait until Nand Flash bit0 is 1 
   wait_nfstat:
        ldr r2,=NFSTAT 
        ldr r3,[r2] 
        tst r3,#0x01 
        beq wait_nfstat 
           
    @ Disable Nand Flash
    ldr r0,=NFCONF 
    ldr r1,[r0] 
    orr r1,r1,#0x8000 
    str r1,[r0] 
    
    @ Initialzie stack 
    ldr sp,=4096 
   
    @ Set arguments and call 
    @ function nand_read defined in nand_read.c
    ldr r0,=0x30000000 
    mov r1,#0
    mov r2,#1024*40
    bl nand_read
   
    @ return
    mov pc,r10


   /* 文件 nand_read.c
    * 作用:从 Nand Flash 中读取一块数据到 SDRAM 中的指定位置
    */
   #define NFCONF (*(volatile unsigned long *)0x4e000000)
   #define NFCMD  (*(volatile unsigned long *)0x4e000004)
   #define NFADDR (*(volatile unsigned long *)0x4e000008)
   #define NFDATA (*(volatile unsigned long *)0x4e00000c)
   #define NFSTAT (*(volatile unsigned long *)0x4e000010)
   #define NFECC  (*(volatile unsigned long *)0x4e000014)
   
   #define NAND_SECTOR_SIZE 512
   #define NAND_BLOCK_MASK  0x1ff
   
   void wait_idle() {
     int i;
     for (i = 0; i < 50000; ++i) ;
   }
   
   int nand_read(unsigned char *buf, unsigned long start_addr, int size){ 
     int i, j; 
     /* 
      * detect the argument 
      */  
     if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { 
       return -1;     
     } 
    
     /* chip Enable */ 
     NFCONF &= ~0x800; 
     for (i=0; i<10; i++) { 
       ; 
     } 
    
     for (i=start_addr; i < (start_addr + size); i+=NAND_SECTOR_SIZE) { 
       NFCMD = 0; 
    
       /* Write Address */ 
       NFADDR = i & 0xff; 
       NFADDR = (i >> 9)  & 0xff; 
       NFADDR = (i >> 17) & 0xff; 
       NFADDR = (i >> 25) & 0xff; 
    
       wait_idle();
    
       for(j=0; j < NAND_SECTOR_SIZE; j++) { 
         *buf++ = (NFDATA & 0xff); 
       } 
     } 
    
     NFCONF |= 0x800;    /* chip disable */ 
     return 0; 
   }


   /* 头文件 serl.h
    * 作用:定义相关寄存器、UART 初始化函数声明、串口读写函数的声明
    */   
   #ifndef __SERL_H__
   #define __SERL_H__
   
   #define GPHCON  (*(volatile unsigned long *)0x56000070)
   
   /* PORT PULL-UP REGISTER*/
   #define GPHUP   (*(volatile unsigned long *)0x56000078)
   
   /* UART FIFO control register 0*/
   #define UFCON0  (*(volatile unsigned long *)0x50000008)
   
   /* UART line control register 0*/
   #define ULCON0  (*(volatile unsigned long *)0x50000000)
   
   /* UART CONTROL REGISTER 0*/
   #define UCON0   (*(volatile unsigned long *)0x50000004)
   
   /* UART modem control register 0*/
   #define UMCON0  (*(volatile unsigned long *)0x5000000C)
   
   /* UART baud rate divisor register 0*/
   #define UBRDIV0 (*(volatile unsigned long *)0x50000028)
   
   /* UART TX/RX STATUS REGISTER 0*/
   #define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
   
   
   #define UTXH0 (*(volatile unsigned char *)0x50000020)
   #define URXH0 (*(volatile unsigned char *)0x50000024)
   
   
   #define TXD0_READY 0x2
   #define RXD0_READY 0x1
   
   void init_uart();
   unsigned char uart_getc();
   void uart_putc(unsigned char ch);
   void uart_puts(unsigned char* src);
   
   #endif


   /* 文件 serl.c*/
   #include "serl.h"
   
   void init_uart() {
     GPHCON |= 0xa0; /* GPH2, GPH3 used as RXD0, TXD0*/
     GPHUP = 0x0c;   /* GPH2, GPH3 poll-up */
   
     ULCON0 = 0x03;  /* normal mode, no parity, one stop bit, 8-bit*/
     UCON0 = 0x05;   /* Loopback mode*/
     UFCON0 = 0x00;  /* not use FIFO*/
     UMCON0 = 0x00;  /* disable flow control*/
     UBRDIV0 = 12;   /* baud rate 57600*/
   }
   
   void uart_putc(unsigned char ch) {
     while (!(UTRSTAT0 & TXD0_READY));
     UTXH0 = ch;
   }
   
   unsigned char uart_getc(){
     while (! (UTRSTAT0 & RXD0_READY));
     return URXH0;
   }
   
   void uart_puts(unsigned char* src) {
     unsigned char *p = src;
     while (*p != '\0') {
       if (*p == 0x0a)
         uart_putc(0x0d);
       uart_putc(*p);
       p++;
     }
   }
  

   /* 
    * 头文件 printf.h
    * 作用:对外提供调用接口 uart_printf
    */   
   #ifndef __PRINTF_HH__
   #define __PRINTF_HH__
   
   void uart_printf(char *fmt, ...);
   
   #endif

   
   /*
    * 文件 printf.c
    * 文件中大部分代码来自 linux 0.11 内核的 vsprintf.c, 只是作了相应的删减,
    * <> 上有更详细的解释
    */
   #include
   #include
   #include
   #include "printf.h"
   #include "serl.h"
   
   #define ZEROPAD  1    /* pad with zero */
   #define SIGN           2    /* unsigned/signed long */
   #define PLUS           4    /* show plus */
   #define SPACE        8    /* space if plus */
   #define LEFT           16   /* left justified */
   #define SPECIAL     32  /* 0x */
   #define LARGE        64  /* use 'ABCDEF' instead of 'abcdef' */
   
   #define is_digit(c) ((c) >= '0' && (c) <= '9')

   #define do_div(n,base) ({    \
         int __res;     \
         __res = ((unsigned long) n) % (unsigned) base; \
         n = ((unsigned long) n) / (unsigned) base; \
         __res; })
   
   static unsigned char sprint_buf[1024];
   
   int strnlen(const char * s, int count)
   {
     const char *sc;
   
     for (sc = s; count-- && *sc != '\0'; ++sc)
       /* nothing */;
     return sc - s;
   }
   
   unsigned char _ctype[] = {
     _C,_C,_C,_C,_C,_C,_C,_C,   /* 0-7 */
     _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
     _C,_C,_C,_C,_C,_C,_C,_C,   /* 16-23 */
     _C,_C,_C,_C,_C,_C,_C,_C,   /* 24-31 */
     _S|_SP,_P,_P,_P,_P,_P,_P,_P,  /* 32-39 */
     _P,_P,_P,_P,_P,_P,_P,_P,   /* 40-47 */
     _D,_D,_D,_D,_D,_D,_D,_D,   /* 48-55 */
     _D,_D,_P,_P,_P,_P,_P,_P,   /* 56-63 */
     _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
     _U,_U,_U,_U,_U,_U,_U,_U,   /* 72-79 */
     _U,_U,_U,_U,_U,_U,_U,_U,   /* 80-87 */
     _U,_U,_U,_P,_P,_P,_P,_P,   /* 88-95 */
     _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
     _L,_L,_L,_L,_L,_L,_L,_L,   /* 104-111 */
     _L,_L,_L,_L,_L,_L,_L,_L,   /* 112-119 */
     _L,_L,_L,_P,_P,_P,_P,_C,   /* 120-127 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 128-143 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 144-159 */
     _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
     _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
     _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
     _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
     _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
     _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
   
   static int skip_atoi(const char **s)
   {
     int i=0;
   
     while (is_digit(**s))
       i = i*10 + *((*s)++) - '0';
     return i;
   }
   
   static char * number(char * str, long num, int base, int size, int precision
          ,int type)
   {
     char c,sign,tmp[66];
     const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
     int i;
   
     if (type & LARGE)
       digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     if (type & LEFT)
       type &= ~ZEROPAD;
     if (base < 2 || base > 36)
       return 0;
     c = (type & ZEROPAD) ? '0' : ' ';
     sign = 0;
     if (type & SIGN) {
       if (num < 0) {
         sign = '-';
         num = -num;
         size--;
       } else if (type & PLUS) {
         sign = '+';
         size--;
       } else if (type & SPACE) {
         sign = ' ';
         size--;
       }
     }
     if (type & SPECIAL) {
       if (base == 16)
         size -= 2;
       else if (base == 8)
         size--;
     }
     i = 0;
     if (num == 0)
       tmp[i++]='0';
     else while (num != 0)
     tmp[i++] = digits[do_div(num,base)];
     if (i > precision)
       precision = i;
     size -= precision;
     if (!(type&(ZEROPAD+LEFT)))
       while(size-->0)
         *str++ = ' ';
     if (sign)
       *str++ = sign;
     if (type & SPECIAL) {
       if (base==8)
         *str++ = '0';
       else if (base==16) {
         *str++ = '0';
         *str++ = digits[33];
       }
     }
     if (!(type & LEFT))
       while (size-- > 0)
         *str++ = c;
     while (i < precision--)
       *str++ = '0';
     while (i-- > 0)
       *str++ = tmp[i];
     while (size-- > 0)
       *str++ = ' ';
     return str;
   }
   
   int __vsprintf(char *buf, const char *fmt, va_list args)
   {
     int len;
     unsigned long num;
     int i, base;
     char * str;
     const char *s;
   
     int flags;  /* flags to number() */
   
     int field_width; /* width of output field */
     int precision;    /* min. # of digits for integers; max number of chars for from string */
     int qualifier;      /* 'h', 'l', or 'L' for integer fields */
   
     for (str=buf ; *fmt ; ++fmt) {
       if (*fmt != '%') {
         *str++ = *fmt;
         continue;
       }
      
       /* process flags */
       flags = 0;
     repeat:
       ++fmt;  /* this also skips first '%' */
       switch (*fmt) {
         case '-': flags |= LEFT; goto repeat;
         case '+': flags |= PLUS; goto repeat;
         case ' ': flags |= SPACE; goto repeat;
         case '#': flags |= SPECIAL; goto repeat;
         case '0': flags |= ZEROPAD; goto repeat;
       }
     
       /* get field width */
       field_width = -1;
       if (is_digit(*fmt))
         field_width = skip_atoi(&fmt);
       else if (*fmt == '*') {
         ++fmt;
         /* it's the next argument */
         field_width = va_arg(args, int);
         if (field_width < 0) {
           field_width = -field_width;
           flags |= LEFT;
         }
       }
   
       /* get the precision */
       precision = -1;
       if (*fmt == '.') {
         ++fmt; 
         if (is_digit(*fmt))
           precision = skip_atoi(&fmt);
         else if (*fmt == '*') {
           ++fmt;
           /* it's the next argument */
           precision = va_arg(args, int);
         }
         if (precision < 0)
           precision = 0;
       }
   
       /* get the conversion qualifier */
       qualifier = -1;
       if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
         qualifier = *fmt;
         ++fmt;
       }
   
       /* default base */
       base = 10;
   
       switch (*fmt) {
       case 'c':
         if (!(flags & LEFT))
           while (--field_width > 0)
               *str++ = ' ';
         *str++ = (unsigned char) va_arg(args, int);
         while (--field_width > 0)
           *str++ = ' ';
         continue;
   
       case 's':
         s = va_arg(args, char *);
         if (!s)
           s = "";
   
         len = strnlen(s, precision);
   
         if (!(flags & LEFT))
           while (len < field_width--)
             *str++ = ' ';
         for (i = 0; i < len; ++i)
          *str++ = *s++;
         while (len < field_width--)
           *str++ = ' ';
         continue;
   
       case 'p':
         if (field_width == -1) {
           field_width = 2*sizeof(void *);
           flags |= ZEROPAD;
         }
         str = number(str,
        (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
         continue;
   
   
       case 'n':
         if (qualifier == 'l') {
           long * ip = va_arg(args, long *);
           *ip = (str - buf);
         } else {
             int * ip = va_arg(args, int *);
             *ip = (str - buf);
         }
         continue;
   
         /* integer number formats - set up the flags and "break" */
       case 'o':
         base = 8;
         break;
   
       case 'X':
         flags |= LARGE;
       case 'x':
         base = 16;
         break;
   
       case 'd':
       case 'i':
         flags |= SIGN;
       case 'u':
         break;
   
       default:
         if (*fmt != '%')
           *str++ = '%';
         if (*fmt)
           *str++ = *fmt;
         else
           --fmt;
         continue;
       }
       if (qualifier == 'l')
         num = va_arg(args, unsigned long);
       else if (qualifier == 'h') {
         num = (unsigned short) va_arg(args, int);
         if (flags & SIGN)
    num = (short) num;
       } else if (flags & SIGN)
         num = va_arg(args, int);
       else
         num = va_arg(args, unsigned int);
       str = number(str, num, base, field_width, precision, flags);
     }
     *str = '\0';
     return str-buf;
   }
   
   /* 这就我们的 printf, 注意我们将参数输出到串口 UART0,而非标准输出*/
   void uart_printf(char *fmt, ...)
   {
     va_list args;
   
     va_start(args, fmt);
     __vsprintf(sprint_buf, fmt,args);
     va_end(args);
   
     /* 将缓冲区的字符输出到串口*/
     uart_puts(sprint_buf);
   }
  

   /* 
    * 文件 main.c
    * 作用:测试代码
    */
   #include "serl.h"
   #include "printf.h"
   
   #define GPFCON (*(volatile unsigned long *)0x56000050)
   #define GPFDAT (*(volatile unsigned long *)0x56000054)
   
   int main()
   { 
     int a = 10;
     init_uart();

     /* 
      * 调用我们自己的 uart_printf,将数据输出到串口,稍后你将
      * 在超级终端上看到显示结果。之所以不叫 printf 是为了不与
      * arm-linux-gcc 的库函数 printf 相冲突
      */
     uart_printf("Hello,Embeded!\n");
     uart_printf("%d\n",a);

     return 0;
   }
  

   最后要说的是 Makefile,这个Makefile 在前面 Makefile的基础上作了很大的改进,不需要你再指定源文件,而是在当前目录下读取扩展名为 .s 和 .c 的文件作为输入文件,你只需指定最终要生成的可执行文件即可,只是它还是不太完美, 你还要指定它依赖的目标文,因为 head.o mem.o flash.o nand_read.o 这些文件被连接生成可执行文件后它们的代码必须位于前 4K, 这样才能保证它们自动被 ARM 加载,从而设置堆栈、初始化内存、读取 Nand Flash 的代码完成自身到 SDRAM 的 self-copying。将来我们会用连接脚本来解决这个问题。

   # Makefile for compiling ARM program
   # Author: Jianbin Wang
   
   CC=arm-linux-gcc
   CFLAGS=-Wall -g -c
   LD=arm-linux-ld
   LDFLAGS:=$(LDFLAGS) -Ttext 0x30000000
   
   INCLUDES=-I./
   CFLAGS:=$(CFLAGS) $(INCLUDES)
   LIBS=-lgcc -L/usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2
   
   CONVERT=arm-linux-objcopy
   CVFLAGS=-O binary -S
   RM=rm -f
   
   SRCDIRS=.
   TARGET=main
   TMPOBJ=$(TARGET)_tmp.o
   SRCS=$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c $(dir)/*.s))
   OBJS=head.o mem.o flash.o nand_read.o main.o printf.o serl.o
   
   all:$(TARGET)
   
   $(TARGET):$(OBJS)
    $(LD) $(LDFLAGS) -o $(TMPOBJ) $(OBJS) $(LIBS)
    $(CONVERT) $(CVFLAGS) $(TMPOBJ) $(TARGET)
   
   $(OBJS):$(SRCS)
    $(CC) $(CFLAGS) $(SRCS)
   
   clean:
    $(RM) $(TARGET)
    $(RM) $(TMPOBJ)
    $(RM) $(OBJS)  


三、编译、烧写、测试
   Make 一下就会生成我们要的文件 main, 将其通过 JTAG 烧入 Nand Flash。用超级终连接到开发板,注意波特率设为 57600,数据位 8,无奇偶校正,停止位1,无数据流控制。现在 Reset 一下的开发板,然后静静的等待吧,生成的二进制文件 main 有 39K 大呢,要等它完全复制到 SDRAM 至少要两三分钟...之后,在超级终端上是不是出现了字符串:

     Hello,Embeded!
     10


关键字:FS2410  串口实现  printf 引用地址:ARM 系列 -- FS2410 开发板上通过串口实现 printf

上一篇:ARM 系列 -- FS2410 开发板上的串口通信编程
下一篇:s3c2410 board.c分析

推荐阅读最新更新时间:2024-03-16 15:22

利用串口与并口实现51内核单片机的在线编程
摘要:详细说明利用并口模拟I2C总线协议,实现Myson MTV230芯片的在线编程(ISP)过程,以及利用PC机的串口通信实现Winbond W78E516B的在线编程(ISP)过程;阐述PC机的串口与并口在单片机开发中的应用。 关键词:并口编程 串口通信 在线编程 ISP MTV230 W78E516B 引 言 1 在线编程简介   51内核的单片机在线编程模式一般分为两大类。一类是使用JTAG协议的在线编程模式。这类模式一般由厂家提供在线编程工具,使用方便。使用这一类模式的单片机价格往往较高,使用的厂商也不多,故不在本文的讨论之列。另一类在线编程模式是使用一条特殊的指令,使单片机进入在线编程模式。在进入在线编程模式后
[应用]
STM32串口打印printf发送中文乱码问题
1、首先要确保使用keil程序正确编译,并且程序经过调试,已经可以正常发送英文字符,但是发送中文字符时乱码。 2、使用记事本打开main.c文件(或其他主程序),点击另存为,在右下方选择编码方式为ANSI,替换原文件即可
[单片机]
STM32F10x 学习笔记6(USART实现串口通讯 2)
这次讲讲利用串口收发中断来进行串口通讯。STM32 上为每个串口分配了一个中断。也就是说无论是发送完成还是收到数据或是数据溢出都产生同一个中断。程序需在中断处理函数中读取状态寄存器(USART_SR)来判断当前的是什么中断。下面的中断映像图给出了这些中断源是如何汇合成最终的中断信号的。图中也给出了如何控制每一个单独的中断源是否起作用。 另外,Cortex-M3 内核中还有个NVIC,可以控制这里的中断信号是否触发中断处理函数的执行,还有这些外部中断的级别。关于NVIC 可以参考《ARM CortexM3 权威指南》,里面讲解的非常详细。 简单的说,为了开启中断,我们需要如下的代码: NVIC_InitType
[单片机]
STM32F10x 学习笔记6(USART<font color='red'>实现</font><font color='red'>串口</font>通讯 2)
STM32 串口中断里面使用printf 出现错误
其实学单片机使用的时候,往往大家都觉得简单,很快就过了,但其实有一些东西是值得深思的,我以前在写程序的时候往往都是发送数据,那么调用重写的printf()函数就可以了,但这次的项目中用到了NRF双全工通讯,这就需要串口的收发,这回就发生了写问题,具体的流水账就不说了。简单说就是串口收可比发讲究多了。 void USART1_IRQHandler(void) //串口1中断服务程序 { u8 i; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//如果寄存器中有数据 { USART_RX_BUF = USART_ReceiveData(USAR
[单片机]
PIC中实现printf函数出现:Warning [2066]
为什么会出现“Warning type qualifier mismatch in assignment”(警告 指定的类型限定符不匹配)? 解答: MPLAB C18提供的库是使用大代码模型编译(-ml 命令行选项)的。默认情况下,MPLAB IDE和编译器将使用小代码模型编译应用程序。例如,随编译器提供的printf函数期望收到“const far rom char *”,但没有为应用程序选择大代码模型时,应用程序实际发送“const near rom char *”到printf 函数。正是far和near间的差别引起了“type qualifier mismatch in assignment”警告。要消除这些警告,
[单片机]
51单片机实现通过串口用计数延时方式发送一串数据
一、使用proteus绘制简单的电路图,用于后续仿真 二、编写程序 /******************************************************************************************************************** ---- @Project: USART ---- @File: main.c ---- @Edit: ZHQ ---- @Version: V1.0 ---- @CreationTime: 20200714 ---- @ModifiedTime: 20200714 ----
[单片机]
51单片机<font color='red'>实现</font>通过<font color='red'>串口</font>用计数延时方式发送一串数据
stm32串口发送16进制字符和16进制数的区别和具体实现方法
在调试一个stm32串口通信时,下位机设置好的发送方式采用串口助手接收后已经可以正常离线解包。但是由于需要实时解包并存储,因此写了一个实时解包存储的上位机,通信正常后接收的数据一直有误。经过单步调试,发现单片机发送的数据帧是字符串,并不是16进制数,而在线解包程序直接是对16进制数进行处理的,这就导致的比如16进制的数0xAA(170),下位机发送的是“AA (字符串),上位机处理的16进制数是41 41(10进制为65*100+65)。查询‘A’的ASCII码可知,‘A’的ASCII码对应的10进制数为65,16进制数为41,也就是说上位机把接收到的16进制字符串当16进制数处理了,所以出错。 解决方法两个,一个是修改下位机
[单片机]
基于Matlab GUI的串口通信编程实现
      0 引言       Matlab是MathWorks公司开发的一种科学计算软件。Matlab运行稳定、可靠、使用方便,是广大科研人员进行科学研究的得力助手。Matlab不仅具有强大的科学计算功能,还具有满足一般要求的数据采集以及界面设计开发功能。Matlab GUI(Graphic User Interface)就是内置于Matlab的进行图形界面开发的模块。       本文利用Matlab GUI设计通过串口进行数据发送和接收的界面,并利用内置于Matlab的串口通信API实现串口数据发送与接收功能。       1 Matlab GUl介绍       启动Matlab后,运行guide命令即可
[网络通信]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved