bmelz 发表于 2015-9-1 09:19:00

这样的工程组织结构是否可行?新手求助,请高手指正

本帖最后由 bmelz 于 2015-9-1 09:40 编辑

工程结构:
user
        inc
                config.h                // 根据电路图配置MCU,主频,引脚配置。
                drivers_cfg.h        // 配置user程序所需的头文件
        src
                main.c                // 用户程序
drivers
        inc
                delay.h                // 根据MCU、主频,进行条件编译
                GPIO.h                // 对GPIO的工作模式进行封装。
                PWM.h                // 提供独立通道PWM设置。该程序是电机等外设提供,user程序不直接使用。
                DC_motor.h       //在PWM的基础上驱动直流电机。user文件直接调用。
        src
                delay.c
                PWM.c               
                DC_motor.c       
思路是:根据电路图把引脚等在config.h里配置好,所需要的外设在drivers_cfg.h配置好。所有的外设封装好后,尽量不再动了。
请高手赐教这个思路是否合适,还有更好的方法吗?
相关文件,以回帖的方式发上来。

bmelz 发表于 2015-9-1 09:21:55

config.h
/**********************************
        *        系统配置文件
        *        MCU型号配置
        *        主频配置
        *        管脚配置
        *******************************/

#ifndef        __CONFIG_H__
#define __CONFIG_H__

//        选择你系统所用MCU,把不用的注释掉。
#define STC15W4K32S4
//#define AT89S51

#define FOSC12        12000000L        //        定义MCU晶振的常用频率
#define FOSC11        11059200L
#define FOSC2424000000L

#define FOSC        FOSC12                //        选择MCU晶振的频率。


/***********************************************
        *        引脚配置,依据电路图把外设的引脚和MCU的引脚对应起来。
        *        注:外设的引脚名称务必和该外设的驱动文件的名称一样,否则无法编译通过。
        *        你需要根据错误提示进行修改。
        ********************************************/

// I2C 引脚配置
#define I2C_SDA                P23
#define I2C_SCL                P22


#define DC_MOTOR1_PWM         P17                //        motor1接在PWM7通道,IO口 P17


#endif

bmelz 发表于 2015-9-1 09:22:46

drivers_cfg.h
/************************************************************
        *        配置user程序所使用的驱动程序
        *        包括MCU自带的功能
        *        不需要用的功能,注释掉该包含文件即可。
        ********************************************************/
#ifndef __DRIVERS_CFG_H__
#define __DRIVERS_CFG_H__

#include "config.h"

//        MCU头文件
#if defined(STC15W4K32S4)
        #include "STC15W4K32S4.h"
#elifdefined(AT89S51)
        #include "AT89X51.h"
#endif

//        GPIO头文件
#if defined(STC15W4K32S4)
        #include "GPIO.h"
#elifdefined(AT89S51)
        #error "AT89S51 hasn't GPIO.h."
#endif

//         延时头文件
#include "delay.h"

//        模拟低速I2C头文件,
#include "I2C.h"

//        定时器头文件

//        串口通信头文件

//        独立通道PWM头文件
#if defined(STC15W4K32S4)
        #include "PWM.h"
#elifdefined(AT89S51)
        #error "AT89S51 hasn't independent PWM channel."
#endif

//        直流电机驱动文件
#include "DC_motor.h"


#endif

bmelz 发表于 2015-9-1 09:23:07

本帖最后由 bmelz 于 2015-9-1 09:27 编辑

GPIO.h

/*************************************************************
        Copyright (C), 2009-2015, C&IIL
        File name: GPIO.h
        Description:
                NULL
        Compiler:
                IDE: Keil C51 9.51, 9.52
                OS:        win8,win8.1
        Function List:
                NULL
        History:
                Author: ZLiang Version: 0.1 Date: 2015/07/22
                Description: Created
*************************************************************/

#ifndef __GPIO_H__
#define __GPIO_H__
#include "config.h"
#include "exmath.h"


//设置Port端口为上拉准双向口。例如:PORT_PullUp(1) 设置P1口为上拉准双向口。
#define _PORT_PullUp(Port)                {P##Port##M1 = 0; P##Port##M0 = 0; }
#define PORT_PullUp(Port)                _PORT_PullUp(Port)

//设置Port端口为强推挽输出。例如:PORT_PP(1) 设置P1口为强推挽输出
#define _PORT_PP(Port)                        {P##Port##M1 = 0; P##Port##M0 = 1; }
#define PORT_PP(Port)                        _PORT_PP(Port)

//设置Port端口为高阻态。例如:PORT_PP(1) 设置P1口为高阻态
#define _PORT_HighZ(Port)                {P##Port##M1 = 1; P##Port##M0 = 0; }
#define PORT_HighZ(Port)                _PORT_HighZ(Port)

//设置Port端口为开漏输出。例如:PORT_PP(1) 设置P1口为开漏输出
#define _PORT_OD(Port)                        {P##Port##M1 = 1; P##Port##M0 = 1; }
#define PORT_OD(Port)                        _PORT_OD(Port)

//设置Port端口的Pin引脚为上拉准双向口。例如:PIN_PullUp(1,2) 设置P12引脚为上拉准双向口。
#define _PIN_PullUp(Port,Pin)        {clrBit(P##Port##M1,Pin);clrBit(P##Port##M0,Pin);}       
#define PIN_PullUp(Port,Pin)        _PIN_PullUp(Port,Pin)

//设置Port端口的Pin引脚为强推挽输出。例如:PIN_PP(1,2) 设置P12引脚为强推挽输出。
#define _PIN_PP(Port,Pin)                {clrBit(P##Port##M1,Pin);setBit(P##Port##M0,Pin);}       
#define PIN_PP(Port,Pin)                _PIN_PP(Port,Pin)

//设置Port端口的Pin引脚为高阻态。例如:PIN_HighZ(1,2) 设置P12引脚为高阻态。
#define _PIN_HighZ(Port,Pin)                {setBit(P##Port##M1,Pin);clrBit(P##Port##M0,Pin);}       
#define PIN_HighZ(Port,Pin)                        _PIN_HighZ(Port,Pin)

//设置Port端口的Pin引脚为开漏输出。例如:PIN_OD(1,2) 设置P12引脚为开漏输出。
#define _PIN_OD(Port,Pin)                {setBit(P##Port##M1,Pin);setBit(P##Port##M0,Pin);}       
#define PIN_OD(Port,Pin)                _PIN_OD(Port,Pin)



#endif

bmelz 发表于 2015-9-1 09:27:41

PWM.h
/************************************************************
        *        功能:STC15W4K58S4 独立PWM功能
        *        Created by ZLiang        2015-07-16
        *        Version: 1.0
        *        revision history:
        *                准双向口输出改为强推挽模式。以满足某些驱动板对大电流的需求。
        *********************************************************/
/**************************** 初始化示例程序 **************************************************
void PWM_Init(void)
{
        ENABLE_PWM_REG();                  //        允许访问PWM特殊功能寄存器
        StopPWM_GEN();                                //         关闭PWM发生器,进行PWM设置       
        setPWM_Period(PWM_Period);       
        setPWM_CLK(SYS_CLK_DIV);
        PWMFDCR |= 0x18;                        //        发生外部异常时,PWM输出设置为高阻模式。异常结束时, 自动回复输出。
        PWMx_IO_init(6);                        //        初始化PWM6通道的端口为强推挽输出。
        PWMx_IO_init(7);
        setPWMxInitLowLevel(6);                //        设置初始电平,通常为低电平。
        setPWMxInitLowLevel(7);
        setPWM_T1(6,PWM6_T1);                //        设置PWM6第一反转点
        setPWM_T2(6,PWM6_T2);                //        设置PWM6第二反转点
        setPWM_T1(7,PWM7_T1);
        setPWM_T2(7,PWM7_T2);
        RunPWM_GEN();                                //        打开PWM发生器,注意此时PWM并不输出。需要使用RunPWMx(x)来使能输出。
//        DISABLE_PWM_REG();
}
********************************************************************************************/
#ifndef __PWM_H__
#define __PWM_H__

#include "config.h"
#include "exmath.h"
#include "STC15W4K32S4.h"

/************************************************************
        *        所有与PWM相关的端口,在上电后均为高阻输入态,必须在程序中将这些
        *        端口设置为双向口或强推挽模式才能正常输出波形。
        *        PWM的输出端口有两组,本驱动程序只用第一组。
        *********************************************************/

#define ENABLE_PWM_REG()         (P_SW2 |= 0x80)                //         允许访问PWM特殊功能寄存器
#define DISABLE_PWM_REG()         (P_SW2 &= 0x7F)                //       
#define RunPWM_GEN()                setBit(PWMCR,7)                //        PWM发生器run
#define StopPWM_GEN()                clrBit(PWMCR,7)                //        PWM发生器停止
#define StopPWMx(x)                stop_PWM(x)                        //        禁止PWM输出,该端口输出低电平。
#define RunPWMx(x)                        setBit(PWMCR,x-2)        //        允许PWM输出


#define PWM_Trigger_ADC()                        setBit(PWMCFG,6)                //        CBTADC = 1;设置PWM计数器归零后触发ADC转换。
#define setPWMxInitHighLevel(x)                setBit(PWMCFG,x-2)                //        设置PWM(x)的起始电平为高电平
#define setPWMxInitLowLevel(x)                clrBit(PWMCFG,x-2)                //        设置PWM(x)的起始电平为低电平

/************************************************************
        *        选择时钟
        *        CLK_SELT_TIMER2 和 CLK_SELT_SYS_DIV不能同时使用
        *********************************************************/
//#define CLK_SELT_TIMER2()        (PWMCKS = 0x10)
#define setPWM_CLK(x)        (PWMCKS = (x-1))        //x = 1~16分频;

/************************************************************
        *        PWM_CYCLE: PWM周期,1-32767之间的任意值。
        *********************************************************/
#define setPWM_Period(x)           (PWMC = x) // PWM周期,1-32767之间的任意值。
#define _setPWM_T1(x,val)         (PWM##x##T1 = val)        // T1翻转点,在使用时x必须为具体值
#define setPWM_T1(x,val)         _setPWM_T1(x,val)
#define _setPWM_T2(x,val)         (PWM##x##T2 = val)        // T2翻转点
#define setPWM_T2(x,val)         _setPWM_T2(x,val)

/************************************************************
        *        PWM中断设置(好多好烦,不常用。未完成,有空再续)。
        *********************************************************/
#define EnablePWM_Int()                        (setBit(PWMCR,6))                                // 允许PWM归零中断,

#define _EnablePWMx_Int(x)                (setBit(PWM##x##CR,2))                        // 允许PWMx中断,x=2~7,CxIF = 1;跳转中断服务程序
#define EnablePWMx_Int(x)                _EnablePWMx_Int(x)

#define _DisablePWMx_Int(x)                (clrBit(PWM##x##CR,2))                        // 关闭PWMx中断,x=2~7
#define DisablePWMx_Int(x)                _DisablePWMx_Int(x)       

#define _EnablePWMx_T1_Int(x)        (setBit(PWM##x##CR,0))                        // 使能PWMx T1翻转时中断,x=2~7,CxIF = 1;跳转中断服务程序
#define EnablePWMx_T1_Int(x)        _EnablePWMx_T1_Int(x)

#define _DisablePWMx_T1_Int(x)        (clrBit(PWM##x##CR,0))                        //
#define DisablePWMx_T1_Int(x)        _DisablePWMx_T1_Int(x)

#define _EnablePWMx_T2_Int(x)        (setBit(PWM##x##CR,1))                        // 使能PWMx T2翻转时中断,x=2~7,CxIF = 1;跳转中断服务程序
#define EnablePWMx_T2_Int(x)        _EnablePWMx_T2_Int(x)

#define _DisablePWMx_T2_Int(x)        (clrBit(PWM##x##CR,1))                        //
#define DisablePWMx_T2_Int(x)        _DisablePWMx_T2_Int(x)

#define getCBIF        getBit(PWMIF,6)                //        获取归零中断标志位       
#define clrCBIF clrBit(PWMIF,6)                //        清除归零中断标志位       
#define getC7IF        getBit(PWMIF,5)                //        获取PWM7翻转中断标志位       
#define clrC7IF clrBit(PWMIF,5)                //        清除PWM7翻转中断标志位       
#define getC6IF        getBit(PWMIF,4)                //        获取PWM6翻转中断标志位       
#define clrC6IF clrBit(PWMIF,4)                //        清除PWM6翻转中断标志位       
#define getC5IF        getBit(PWMIF,3)                //        获取PWM5翻转中断标志位       
#define clrC5IF clrBit(PWMIF,3)                //        清除PWM5翻转中断标志位       
#define getC4IF        getBit(PWMIF,2)                //        获取PWM4翻转中断标志位       
#define clrC4IF clrBit(PWMIF,2)                //        清除PWM4翻转中断标志位       
#define getC3IF        getBit(PWMIF,1)                //        获取PWM3翻转中断标志位       
#define clrC3IF clrBit(PWMIF,1)                //        清除PWM3翻转中断标志位       
#define getC2IF        getBit(PWMIF,0)                //        获取PWM2翻转中断标志位       
#define clrC2IF clrBit(PWMIF,0)                //        清除PWM2翻转中断标志位       

#define set_PWM_duty(x,duty)        {setPWM_T1(x,0);setPWM_T2(x,duty);}        //设置通道x的占空比duty

/************************************************************
        *        初始化PWM端口,设置为强推挽模式,并禁止PWM输出,防止误动作
        *********************************************************/
extern void PWMx_IO_init(uint8_t x);

/************************************************************
        *        关闭PWM通道,使之输出为低电平。
        *        务必在PWM初始化后,使用。
        *********************************************************/
extern void stop_PWM(uint8_t x);

#endif

bmelz 发表于 2015-9-1 09:31:37

DC_motor.h
#ifndef __DC_MOTOR_H__
#define __DC_MOTOR_H__

#include "config.h"
#include "PWM.h"

//        检查驱动程序引脚名与引脚配置引脚名的一致性。如果不一致则提示错误。
#ifndef DC_MOTOR1_PWM
        #error "The pin-name should be DC_MOTOR1_PWM in config.h"
#endif

#define MOTOR_F                                1000                        //        设定载波频率1KHz,所有电机的载波频率一样。
#define MOTOR1_CH                        7                                //        motor1接在P17端口
#define set_motor1_duty(duty)        setPWM_T2(MOTOR1_CH,duty)        //        设定motor1的占空比
#define run_motor1()                        RunPWMx(MOTOR1_CH)                        //        motor1开始转动
#define stop_motor1()                        StopPWMx(MOTOR1_CH)                        //        motor1停止转动


extern void DC_motor1_init(void);

#endif

磊磊映画 发表于 2015-9-1 09:31:49

是不是还要加上中间层?应用层直接跟底层打交道是不是太直接了,中间层通过底层抽象出一部分应用的接口来。应用层在去中间层调用,方便后期维护升级

bmelz 发表于 2015-9-1 10:26:48

磊磊映画 发表于 2015-9-1 09:31
是不是还要加上中间层?应用层直接跟底层打交道是不是太直接了,中间层通过底层抽象出一部分应用的接口来。 ...

谢谢你的建议!现在就是不知道哪些东西应该放到中间层,I2C,PWM, UART吗?我现在想把PWM当作中间层,应用层是DC_motor。但是想不好文件怎么放?也不知道这样可对,恳请您赐教!

磊磊映画 发表于 2015-9-1 11:43:34

bmelz 发表于 2015-9-1 10:26
谢谢你的建议!现在就是不知道哪些东西应该放到中间层,I2C,PWM, UART吗?我现在想把PWM当作中间层,应 ...

以IIC为例,工控板上应该有EEPROM,平时系统启动也从EEPROM中启动的,读取数据,配置参数等
1.IIC总线上上的读数据 写数据 IIC停止 等就应该放到底层
void iic_read(u8 addr)
void iic_write(u8 addr)
2.比如说你在EEPROM中设置了一个地址里面保存着你的开机次数这个就应该放在中间层
它会调用底层的读写函数
u8 util_begin_times(u8 addr)
{   
   u8 times;
   times=iic_read(addr);
   times++;
   iic_write(times);   
}
3.大概就是这样应用层还会调用中间层的,最终实现功能

bmelz 发表于 2015-9-1 12:20:45

磊磊映画 发表于 2015-9-1 11:43
以IIC为例,工控板上应该有EEPROM,平时系统启动也从EEPROM中启动的,读取数据,配置参数等
1.IIC总线上 ...

大概明白了,非常感谢您。

GZZXB 发表于 2015-11-12 22:28:59

代码很规范
页: [1]
查看完整版本: 这样的工程组织结构是否可行?新手求助,请高手指正