这样的工程组织结构是否可行?新手求助,请高手指正
本帖最后由 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配置好。所有的外设封装好后,尽量不再动了。
请高手赐教这个思路是否合适,还有更好的方法吗?
相关文件,以回帖的方式发上来。 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 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: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 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
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
是不是还要加上中间层?应用层直接跟底层打交道是不是太直接了,中间层通过底层抽象出一部分应用的接口来。 ...
谢谢你的建议!现在就是不知道哪些东西应该放到中间层,I2C,PWM, UART吗?我现在想把PWM当作中间层,应用层是DC_motor。但是想不好文件怎么放?也不知道这样可对,恳请您赐教! 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.大概就是这样应用层还会调用中间层的,最终实现功能
磊磊映画 发表于 2015-9-1 11:43
以IIC为例,工控板上应该有EEPROM,平时系统启动也从EEPROM中启动的,读取数据,配置参数等
1.IIC总线上 ...
大概明白了,非常感谢您。 代码很规范
页:
[1]