chpl 发表于 2014-9-3 17:59:54

在51单片机上写外围设备的驱动有必要么?

打算给C8051F040的一些外围器件(ADC, SMBUS, UART,...)写驱动并提供统一的数据传输接口(并向上封装到能给外围器件分配虚拟寻址地址的层次),但是这大大增加了ISR的执行时间和接口函数的额外空间。
想知道各位大大是如何考虑的。

xiayuan 发表于 2014-9-4 07:21:54

这个应该看系统的大小和实际需求吧。单片机本来就是精简。

笑笑我笑了 发表于 2014-9-4 07:32:41

出于锻炼自己编程能力的角度考虑是挺好的。

别有洞天下 发表于 2014-9-4 10:32:38

支持一下来,新人

severewinner 发表于 2014-9-4 10:40:14

取决于你要做什么,你以都用这个系列的芯片还是就是练习,或者你想造福后人?
做外围驱动很锻炼模块化设计,还有时序的控制。所以看你的需求了

chpl 发表于 2014-9-4 12:21:58

severewinner 发表于 2014-9-4 10:40
取决于你要做什么,你以都用这个系列的芯片还是就是练习,或者你想造福后人?
做外围驱动很锻炼模块化设计 ...

看起来还是练习的成分多一点。。
那就当作多了解下这方面的知识,再请大大帮看下代码。。
UART
#include "uart.h"

unsigned char idata UART0_Stat;//BUSY:1
unsigned char idata UART0_DevAdd;
unsigned char xdata* idata UART0_TxCache;
unsigned char idata UART0_TxLen;
unsigned char xdata* idata UART0_RxCache;
unsigned char idata UART0_RxLen;
/*
TransmissionCache:
        if Multiprocessor Communications
                the UART0_DevAdd is the Target Address
        or it would be blank
        UART0_TxCache is the data pointer
        UART0_RxLen is the data's length
ReceptionCache:
       
*/
Status UART0_O(unsigned char DevAdd, unsigned char xdata* TxCache, unsigned char TxLen){
        if( UART0_Stat & UART0_Busy ) return 0; //Fail|Buf_full;
        SFRPAGE_SAVED = SFRPAGE;
        SFRPAGE = UART0_PAGE;
        UART0_Stat |= UART0_Busy;
        UART0_DevAdd = DevAdd;
        UART0_TxCache = TxCache;
        UART0_TxLen = TxLen;
        SBUF0 = *UART0_TxCache++;
        UART0_TxLen--;
        SFRPAGE = SFRPAGE_SAVED;
        return 1; //complete|sending;
}

void UART0_Interrupt(void) interrupt 4 {
       
        if ( RI0 == 1 ){
                RI0 = 0;
                *UART0_RxCache++ = SBUF0;//*UART0_RxCache point to the next position of a string's tail
                UART0_RxLen++;
        }
        if( TI0 == 1 ){
                TI0 = 0;
                if( UART0_TxLen != 0 ){
                        SBUF0 = *UART0_TxCache++;
                        UART0_TxLen--;
                        }else{
                        UART0_Stat &= ~UART0_Busy;
                }
        }
        return ;
}
一个简单的UART驱动,和一个相对复杂的SMBUS驱动
#include "smbus.h"
#include "gernic.h"

unsigned char idata SMBUS0_Stat;//BUSY:1 RnW:1
unsigned char idata SMBUS0_DevAdd;
unsigned char xdata* idata SMBUS0_AddCache;
unsigned char idata SMBUS0_AddLen;
unsigned char xdata* idata SMBUS0_TxRxCache;
unsigned char idata SMBUS0_TxRxLen;

Status SMBUS0_IO(uint8 DevAdd, unsigned char xdata *AddCache, unsigned char xdata *TxRxCache, uint8 AddLen, uint8 TxRxLen){
        if( SMBUS0_Stat & SMBUS0_Busy ) return 0; //Fail|Buf_full;
        SMBUS0_Stat |= SMBUS0_Busy;//置位忙
        if( (DevAdd & 0x01) == READ){
                SMBUS0_Stat |= READ;
        }else{
                SMBUS0_Stat |= WRITE;
        }       
        SMBUS0_DevAdd = DevAdd & 0xFE;//放入目标地址和写操作
        SMBUS0_AddCache = AddCache;//放入目标数据位置
        SMBUS0_TxRxCache = TxRxCache;//放入数据地址
        SMBUS0_AddLen = AddLen;//放入地址长度
        SMBUS0_TxRxLen = TxRxLen;//放入数据长度
        SFRPAGE_SAVED = SFRPAGE;//开始发送
        SFRPAGE = SMB0_PAGE;
        STA = 1;
        SFRPAGE = SFRPAGE_SAVED;
        return 1; //complete|sending;
}

void SMBUS0_ISR (void) interrupt 7 {

        SI = 0;
        switch( SMB0STA ){
                case SMB_MSTART ://发送了开始位 ok
                case SMB_MRPSTART ://发送了重新开始位 ok
                        SMB0DAT = SMBUS0_DevAdd; //发送目标地址
                        STA = 0;//清零STA
                        break;
                case SMB_MTADDACK : //发送目标地址收到ACK
                case SMB_MTDBACK : //发送数据收到ACK
                        if( SMBUS0_AddLen != 0 ){//要发送地址
                                SMB0DAT = *SMBUS0_AddCache++;
                                SMBUS0_AddLen--;
                                break;
                        }
                        if( (SMBUS0_Stat & READ) == READ ){
                                SMBUS0_Stat |= READ;
                                STA = 1;//发送重复开始
                                break;
                        }
                        if( SMBUS0_TxRxLen != 0 ){//要发送的数据
                                SMB0DAT = *SMBUS0_TxRxCache++;
                                SMBUS0_TxRxLen--;
                                break;
                        }
                        STO = 1;//结束传输
                        SMBUS0_Stat &= ~SMBUS_BUSY;//SMBUS闲
                        break;
                case SMB_MRDBACK :                       
                        *SMBUS0_TxRxCache++ = SMB0DAT;
                case SMB_MRADDACK :
                        if( --SMBUS0_TxRxLen != 0 ){ //接收完毕?
                                AA = 1;
                        }else{
                                AA = 0;
                        }
                        break;
                case SMB_MRDBNACK :
                        *SMBUS0_TxRxCache = SMB0DAT;
                        STO = 1;
                        SMBUS0_Stat &= ~SMBUS0_Busy;
                        break;
                default:
                        SMB0CN &= ~0x74;               //重设
                        SMB0CN |= 0x40;
        }

        return ;
}
是否用汇编写,接口用Blocking还是Non-Blocking,可以精简信号传递么,在这些方面尚有疑问。
简而言之就是还是想找明灯讨个最优化设计的大概信息,就练习模块化设计而言。
页: [1]
查看完整版本: 在51单片机上写外围设备的驱动有必要么?