搜索
bottom↓
回复: 13

求一个C语言编程技巧

[复制链接]

出0入0汤圆

发表于 2013-9-26 09:52:00 | 显示全部楼层 |阅读模式
假如我用单片机的几个IO口通过一定的时序操作一个设备,这些IO口已经在程序中宏定义过了,相关的驱动程序在此宏定义基础上也已经写好。但是我想在程序中动态的分时去操作多台一模一样的设备,仅仅是IO口不同而已。如果能在程序中动态的去改变那些设备IO口的宏定义即可,但这个显然不行。有没有其他的办法?也就是说,所有设备仅仅是物理IO不同,但在程序运行期间共用一套驱动函数。

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2013-9-26 10:42:01 | 显示全部楼层
物理层和底层分离

出0入0汤圆

发表于 2013-9-26 10:45:52 | 显示全部楼层
可能用指针也比较方便 寄存器也是个地址吧?

出0入0汤圆

 楼主| 发表于 2013-9-26 10:50:36 | 显示全部楼层
HadesHe 发表于 2013-9-26 10:42
物理层和底层分离


我现在的驱动相关的函数特别多,要操作不同的设备,也就是IO口定义不同而已,我就想,有什么方法,能让所有的驱动函数可以共用。
我想到一个方法,是所有函数多加个参数,判断是哪个设备,但因为函数太多了,这样也比较麻烦。

出0入4汤圆

发表于 2013-9-26 10:52:59 | 显示全部楼层
wuha 发表于 2013-9-26 10:50
我现在的驱动相关的函数特别多,要操作不同的设备,也就是IO口定义不同而已,我就想,有什么方法,能让所 ...

与程序时,过程运算不应该用到IO口的,IO只作为输入和输出时使用.
如果是这样写的话,当你输出时,判断一下输出到哪个IO不就可以了?!

出0入0汤圆

发表于 2013-9-26 10:57:24 | 显示全部楼层
樓主似乎不知道,帶#的語句,執行者是編譯器,而非單片機?
所以你需要的是一系列的(指針)變量,而非宏定義。

出0入0汤圆

发表于 2013-9-26 11:01:01 | 显示全部楼层
最简单的方式,把你的IO宏定义操作,改成函数操作即可

出0入0汤圆

 楼主| 发表于 2013-9-26 11:01:38 | 显示全部楼层
qlb1234 发表于 2013-9-26 10:57
樓主似乎不知道,帶#的語句,執行者是編譯器,而非單片機?
所以你需要的是一系列的(指針)變量,而非宏定 ...

嗯,宏定义我知道不行,看来只能用函数指针了。把IO口的动作封装成函数,然后在调用所有驱动程序时,把最底层函数通过指针指向不同的IO口动作函数。

出0入0汤圆

发表于 2013-9-26 11:03:27 | 显示全部楼层
比如
  1. #include <xxx.h>
  2. void td(int time, char * p)
  3. {
  4.     if(time == 1)
  5.     {
  6.         p = P1;
  7.     }
  8.     else
  9.     {
  10.         p = P2;
  11.     }
  12. }

  13. void op(void)
  14. {
  15.     *p = 0x01;
  16. }

  17. void main(void)
  18. {
  19.     char * p;
  20.     while(1)
  21.     {
  22.         td(1, p);
  23.         op();
  24.         td(2, p);
  25.         op();
  26.     }
  27. }
复制代码

出0入0汤圆

发表于 2013-9-26 13:39:08 | 显示全部楼层
这里有同样问题:http://www.amobbs.com/thread-5532088-1-1.html

出0入0汤圆

 楼主| 发表于 2013-9-26 15:23:07 | 显示全部楼层
wxty 发表于 2013-9-26 13:39
这里有同样问题:http://www.amobbs.com/thread-5532088-1-1.html

谢谢,我定义了个全局变量,直接在最底层操作IO口时判断全局变量,从而操作不同的IO口,所有上层函数都不需要动了。使用时改变全局变量就行了。这样理解简单,我已经改好了。

出0入296汤圆

发表于 2013-9-26 18:22:23 | 显示全部楼层
wuha 发表于 2013-9-26 15:23
谢谢,我定义了个全局变量,直接在最底层操作IO口时判断全局变量,从而操作不同的IO口,所有上层函数都不 ...

用全局变量来处理这个问题,你这是一个悲剧的开始……
从你的描述来看,代码结构并不简单……我要提醒你,由于你使用了全局变量,这就成为了多个任务的共享资源,
你要为这个全局变量,以及全局变量直接相关的底层IO建立临界区,否则,在涉及到简单的多任务,甚至是前后台
的情况下,很有可能会出现问题。

出0入0汤圆

 楼主| 发表于 2013-9-27 01:59:19 | 显示全部楼层
Gorgon_Meducer 发表于 2013-9-26 18:22
用全局变量来处理这个问题,你这是一个悲剧的开始……
从你的描述来看,代码结构并不简单……我要提醒你 ...

谢傻孩子提醒,我这个虽然驱动相关的功能程序复杂了些,但主程序调用还是比较简单的分时调用,我会注意这点的。

出0入0汤圆

发表于 2013-9-27 09:22:48 | 显示全部楼层
  1. #define ADC1_Port           GPIOB     
  2. #define ADC1_SCK_Pin        ADC_SCK1
  3. #define ADC1_SDA_Pin        ADC_SDA1

  4. #define ADC2_Port           GPIOB
  5. #define ADC2_SCK_Pin        ADC_SCK2
  6. #define ADC2_SDA_Pin        ADC_SDA2

  7. #define ADC3_Port           GPIOA
  8. #define ADC3_SCK_Pin        ADC_SCK3
  9. #define ADC3_SDA_Pin        ADC_SDA3

  10. #define ADC4_Port           GPIOB
  11. #define ADC4_SCK_Pin        ADC_SCK4
  12. #define ADC4_SDA_Pin        ADC_SDA4


  13. #define CS5513_1                0x00
  14. #define CS5513_2                0x01
  15. #define CS5513_3                0x02
  16. #define CS5513_4                0x03

  17. /** @defgroup Private_TypesDefinitions
  18.   * @{
  19.   */
  20. typedef void    (*pFunctionWriteBit)(void);
  21. typedef uint8_t (*pFunctionReadBit)(void);
  22. typedef enum    SWITCHTAG   {OFF,ON} SWITCH;


  23. /** @defgroup Private_Defines
  24.   * @{
  25.   */


  26. /** @defgroup Private_Macros
  27.   * @{
  28.   */


  29. /** @defgroup Private_Variables
  30.   * @{
  31.   */
  32.   
  33. SWITCH   ADC_SAMPLE_SWITCH[4]  =   {OFF,OFF,OFF,OFF};
  34. uint32_t ADC_SAMPLE_COUNT[4]   =   {  0,  0,  0,  0};
  35. /** @defgroup Private_FunctionPrototypes
  36.   * @{
  37.   */

  38. /** @defgroup Private_Functions
  39.   * @{
  40.   */
  41. void SetADC_SCK1(void)  {GPIO_SetBits(ADC1_Port,ADC_SCK1);}
  42. void SetADC_SCK2(void)  {GPIO_SetBits(ADC2_Port,ADC_SCK2);}
  43. void SetADC_SCK3(void)  {GPIO_SetBits(ADC3_Port,ADC_SCK3);}
  44. void SetADC_SCK4(void)  {GPIO_SetBits(ADC4_Port,ADC_SCK4);}

  45. void ResetADC_SCK1(void){GPIO_ResetBits(ADC1_Port,ADC_SCK1);}
  46. void ResetADC_SCK2(void){GPIO_ResetBits(ADC2_Port,ADC_SCK2);}
  47. void ResetADC_SCK3(void){GPIO_ResetBits(ADC3_Port,ADC_SCK3);}
  48. void ResetADC_SCK4(void){GPIO_ResetBits(ADC4_Port,ADC_SCK4);}


  49. uint8_t ReadADC_SDA1(void){return GPIO_ReadInputDataBit(ADC1_Port,ADC1_SDA_Pin);}
  50. uint8_t ReadADC_SDA2(void){return GPIO_ReadInputDataBit(ADC2_Port,ADC2_SDA_Pin);}
  51. uint8_t ReadADC_SDA3(void){return GPIO_ReadInputDataBit(ADC3_Port,ADC3_SDA_Pin);}
  52. uint8_t ReadADC_SDA4(void){return GPIO_ReadInputDataBit(ADC4_Port,ADC4_SDA_Pin);}

  53. /* ·´Ïò */
  54. const pFunctionWriteBit SetSck[4]             = {
  55.                                             ResetADC_SCK1,
  56.                                             ResetADC_SCK2,
  57.                                             ResetADC_SCK3,
  58.                                             ResetADC_SCK4
  59.                                           };
  60. /* ·´Ïò */
  61. const pFunctionWriteBit ResetSck[4]    =  {
  62.                                             SetADC_SCK1,
  63.                                             SetADC_SCK2,
  64.                                             SetADC_SCK3,
  65.                                             SetADC_SCK4
  66.                                           };

  67. const pFunctionReadBit ReadSda[4]      =  {
  68.                                             ReadADC_SDA1,
  69.                                             ReadADC_SDA2,
  70.                                             ReadADC_SDA3,
  71.                                             ReadADC_SDA4
  72.                                           };
  73.   
  74. void EnableADCPinExitInterrupt(uint8_t channel)
  75. {
  76.    
  77. }

  78. void DisableADCPinExitInterrupt(uint8_t channel)
  79. {
  80.    
  81. }

  82. ERRORCODE EnableSample(uint8_t channel)
  83. {
  84.     /* reset sclk */
  85.     ResetSck[channel]();
  86.     //SetSck[channel]();
  87.     /* reset count */
  88.     ADC_SAMPLE_COUNT[channel] = 0;
  89.     /* enable exit sda high to low interrupt */
  90.    
  91.     EnableADCPinExitInterrupt(channel);
  92.     ADC_SAMPLE_SWITCH[channel] = ON;
  93.    
  94.     /* if count > 5 the data is valid */
  95.     return SUCCEED;
  96. }

  97. ERRORCODE DisableSample(uint8_t channel)
  98. {
  99.     /* set sck */
  100.     SetSck[channel]();
  101.     //ResetSck[channel]();
  102.     /* reset count */
  103.     ADC_SAMPLE_COUNT[channel] = 0xFFFFFFFF;
  104.     /* disable exit sda high to low interrupt */
  105.     //DISABLE_EXIT;
  106.     DisableADCPinExitInterrupt(channel);
  107.     ADC_SAMPLE_SWITCH[channel] = OFF;
  108.    
  109.     /*  */
  110.     return SUCCEED;
  111. }

  112. ERRORCODE GetADCSampleValue(uint8_t channel,uint32_t *value)
  113. {
  114.     uint8_t count = 0;   
  115.     *value = 0;
  116.     for (count = 0;count < 24;count++)
  117.     {
  118.         /* set sck high  */
  119.         SetSck[channel]();
  120.         SetSck[channel]();
  121.         SetSck[channel]();
  122.         SetSck[channel]();
  123.         /* read sda      */
  124.         *value |= (uint32_t)ReadSda[channel]();
  125.         (*value) <<= 1;
  126.         SetSck[channel]();
  127.         SetSck[channel]();
  128.         SetSck[channel]();
  129.         SetSck[channel]();
  130.         SetSck[channel]();
  131.         
  132.         /* reset sck low */
  133.         ResetSck[channel]();
  134.         ResetSck[channel]();
  135.         ResetSck[channel]();
  136.         ResetSck[channel]();
  137. //        ResetSck[channel]();/* Just for Delay */
  138. //        ResetSck[channel]();
  139.     }
  140.     (*value) >>= 1;
  141.     //SetSck[channel]();
  142.    
  143.     return SUCCEED;
  144. }
  145. 小思路···
复制代码
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 00:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表