且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

tiny4412 UART for C printf Demo

更新时间:2022-08-12 20:46:25

/**************************************************************************
 *                 tiny4412 UART for C printf Demo
 * 声明:
 *      这主要是在tiny4412的串口上实现C语言中的printf函数的Demo,当然,
 *  除了实现printf,还提供了由此产生的一些常用函数(ntoi,trim)。
 *
 *                          2015-7-5 晴 深圳 南山平山村 曾剑锋
 *************************************************************************/

                        \\\\\-*- 目录 -*-/////
                        |  一、cat uart.h
                        |  二、cat uart.c
                        \\\\\\\\\\\//////////


一、cat uart.h
    #ifndef  __UART_H__
        #define  __UART_H__
        
        typedef  volatile unsigned int  U32 ; 

        //Uart
        #define   GPA0CON   *(U32 *)0x11400000
        
        #define  com0base   0x13800000
        
        //com3
        #define   ULCON0    *(U32 *)(com0base + 0x0000)
        #define   UCON0     *(U32 *)(com0base + 0x0004)
        #define   UFCON0    *(U32 *)(com0base + 0x0008)
        #define   UMCON0    *(U32 *)(com0base + 0x000C)
        #define   UTRSTAT0  *(U32 *)(com0base + 0x0010)
        #define   UERSTAT0  *(U32 *)(com0base + 0x0014)
        #define   UFSTAT0   *(U32 *)(com0base + 0x0018)
        #define   UMSTAT0   *(U32 *)(com0base + 0x001C)
        #define   UTXH0     *(U32 *)(com0base + 0x0020)
        #define   URXH0     *(U32 *)(com0base + 0x0024)
        #define   UBRDIV0   *(U32 *)(com0base + 0x0028)
        #define   UFRACVAL0 *(U32 *)(com0base + 0x002C)
        #define   UINTP0    *(U32 *)(com0base + 0x0030)
    
        // 初始化Uart0
        int init_uart(void) 
        // 获取一个字符
        char get_char(void);
        // 输出一个字符
        void put_char(char ch);
        // 获取一个字符串
        int gets(char* string);
        // 输出一个字符串
        int puts(char* string);
        // 字符串比较
        int strcmp(char* srcstr, char* diststr);
        // 打印输出printf
        int printf(char* fmt, ...);
        // 计算字符串的长度
        int strlen(char* str);
        // 输出一个数字
        void put_num(int num);
        // 以十六进制输出数字
        void put_hex(int num);
        // 数字转换成十六进制字符
        char ntohex(int num);
        // 以2进制输出数字
        void put_bin(int num);
        // 输出一行字符串
        void put_line(char* string);
        // 修剪字符串右侧的空白字符 
        char* trimr(char* string);
        // 修剪字符串左侧的空白字符
        char* triml(char* string);
        // 修剪字符串左右的空白字符
        char* trim(char* string);
    
    #endif   //__UART_H__

二、cat uart.c
    #include "uart.h"
    
    /**
     * 初始化Uart0
     */
    int init_uart(void) 
    {
        //configure  RX0,TX0 as Uart 
        GPA0CON &= ~(0xff); 
        GPA0CON |= 0x22; 
    
        //controler
        
        //configure Uart as 8N1
        ULCON0  &= ~0x3 ;
        ULCON0  |= 0x3 ; 
    
        //set RX TX  as  polling mode
        UCON0  &= ~0x3f ; 
        UCON0  |= 5 ; 
    
        //set baud rate as 115200     Pclock as  100M
        UBRDIV0 = 53 ; 
        UFRACVAL0 = 4 ; 
    }
    
    char get_char(void)
    {
        /**
         * 尽可能等待数据
         */
        while((UTRSTAT0 & 0x1) == 0)
            delays( 0xffff);
        return URXH0;
    }
    
    void put_char(char ch)
    {
        /**
         * 一定要等待数据写完
         */
        while((UTRSTAT0 & 0x4) == 0)
                delays( 0xffff);
        UTXH0 = ch;
    }
    
    int gets(char* string)
    {
        puts("[zjf@root ]# ");
    
        int i = 0;
        for(i = 0; i < 1024-1; i++){
    
            while((UTRSTAT0 & 0x1) == 0)
                delays( 0xffffff);
    
            string[i] = URXH0;
            if(string[i] == '\r'){
    
                put_char('\n');
                put_char('\r');
    
                string[i] = '\0';
    
                return i+1;
            }
            if(string[i] == '\b'){
                if (i == 0){
                    string[i] = '\0';
                    continue;
                }
                //清除当前输入的'\b', 并换成'\0',并用空格覆盖前面那个字符,同时输出一次
                string[i--] = '\0';
                string[i] = ' ';
                put_char('\r');
                puts("[zjf@root ]# ");
                puts(string);
    
                //将前面换成空格的字符换成'\0'结束符, 在输出一次,
                //主要是为了让光标往前移一个字符
                string[i--] = '\0';
                put_char('\r');
                puts("[zjf@root ]# ");
                puts(string);
                continue;
            }
            if(string[i] == 3){ //ctrl+c
                //清除string中所有的数据
                int j = 0;
                for(j = 0; j <= i; j++){
                    string[j] = '\0';
                }
                //输出<ctrl+c>等字符
                puts("<Ctrl+c>\r\n");
                puts("[zjf@root ]# ");
                //将i置为起始位
                i = -1;
                continue;
            }
            if(string[i] == 4){
                //清除string中所有的数据
                int j = 0;
                for(j = 0; j <= i; j++){
                    string[j] = '\0';
                }
                //输出<ctrl+c>等字符
                puts("<Ctrl+d>\r\n");
                return 0;
            }
            put_char(string[i]);
        }
    }
    
    int puts(char* string)
    {
        int i = 0;
        while(string[i]){
            put_char(string[i]);
            i++;
        }
        return i;
    }

    void put_line(char* string)
    {
        puts(string);
        puts("\r\n");
    }
    
    int strcmp(char* srcstr, char* diststr)
    {
        while((*srcstr) && (*diststr) && ((*srcstr) == (*diststr))){
            srcstr++;
            diststr++;
        }
        return (*srcstr)-(*diststr);
    }
    
    int bzero(char* string, int size)
    {
        if(size < 0){
            return 0;
        }
    
        int i = 0;
        if(strlen(string) >= size){
            for (i = 0; i < size; i++){
                string[i] = '\0';
            }
            return i;
        }else{
            int length = strlen(string);
            for (i = 0; i < length; i++){
                string[i] = '\0';
            }
            return length;
        }
    }
    
    int printf(char* fmt, ...)
    {
        unsigned int ** begin_add = (unsigned int **)(&fmt);
        char ch = '\0';
        int num = 0;
        while (ch = (*(fmt++))) {
            if (ch == '%') {
                ch = (*(fmt++));
                if (ch == 'd') {
                    num = (int)(*(++begin_add));
                    if(num >= 0){
                        put_num(num);
                    }else{
                        put_char('-');
                        put_num((~num)+1);
                    }
                }
                if (ch == 's') {
                    puts((char *)(*(++begin_add)));
                }
                if ((ch == 'x') || (ch == 'p')){
                    put_char('0');
                    put_char('x');
                    put_hex((int)(*(++begin_add)));
                }
                if (ch == 'b') {
                    put_char('0');
                    put_char('b');
                    put_bin((int)(*(++begin_add)));
                }
                if (ch == '%'){
                    put_char(ch);
                }
    
                continue;
            }
            put_char(ch);
        }
    }
    
    void put_num(int num){
        if(num < 10){
            put_char(num+'0');
            return;
        }
    
        put_num(num/10);
    
        put_char(num%10+'0');
    }
    
    int atoi (char* string)
    {
        int i = 0;
        trim(string);
        char ch = '\0';
        int num = 0;
        if(string[0] != '-'){
            while(ch = string[i++]){
                if ((ch < '0') || (ch > '9')) {
                    return 99999999;
                }
                num *= 10;
                num += (ch-'0');
            }
        }else{
            //pass the '-'
            i++;
            while(ch = string[i++]){
                if ((ch < '0') || (ch > '9')) {
                    return 99999999;
                }
                num *= 10;
                num += (ch-'0');
            }
            num = (~num) + 1;
        }
        return num;
    }
    
    int strlen(char* str)
    {
        int count = 0;
        while(str[count++]);
        return count-1;
    }

    void put_bin(int num){
        if(num < 2){
            put_char(num+'0');
            return ;
        }
        put_bin(num/2);
        put_char(num%2+'0');
    }
    
    void put_hex(int num){
        char ch = '\0';
        if(num < 16){
            ch = ntohex(num);
            put_char(ch);
            return ;
        }
        put_hex(num/16);
        ch = ntohex(num%16);
        put_char(ch);
    }
    
    char ntohex(int num)
    {
        if (num < 0 || num > 15) {
            return '\0';
        }
        if (num < 10) {
            return '0'+num;
        }
        switch (num) {
            case 10 :
                return 'A';
            case 11 :
                return 'B';
            case 12 :
                return 'C';
            case 13 :
                return 'D';
            case 14 :
                return 'E';
            case 15 :
                return 'F';
        }
    }
    
    char* trimr(char* string)
    {
        if(string == '\0' || string[0] == '\0')
            return '\0';
    
        int i = 0;
        i = strlen(string);
        for(i--; i >= 0; i--){
            if((string[i] == ' ') || (string[i] == '\t')){
                string[i] = '\0';
            }else{
                return string;
            }
        }
    }
    
    char* triml(char* string)
    {
        if(string == '\0' || string[0] == '\0')
            return '\0';
    
        int i = 0;
        int j = 0;
        while((string[i] == ' ') || (string[i] == '\t'))
            i++;
        while(string[i]){
            string[j++] = string[i++];
        }
        string[j] = '\0';
        return string;
    }
    
    char * trim(char* string)
    {
        if(string == '\0' || string[0] == '\0')
            return '\0';
        return trimr(triml(string));
    }