独闷闷网

 找回密码
 立即注册
搜索
查看: 5262|回复: 2
打印 上一主题 下一主题
收起左侧

[分享] CH452A按键扫描驱动C程序分享给大家。

[复制链接]
跳转到指定楼层
楼主
发表于 2015-7-10 11:56:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 jianhong_wu 于 2015-7-11 11:50 编辑

坚鸿-深圳:
最近做项目需要用到CH452A按键扫描集成驱动芯片,现在把已经测试通过了的驱动代码分享给大家,供大家参考。
我用的是stm32f407单片机,主频率达到168MHz。
硬件连接简述:
CH452A芯片可以驱动8x8一共64个按键,但是本程序只是驱动4x4一共16个按键。硬件上行列扫描的连接是分别用CH452A芯片的DIG7至DIG4,以及SEG7至SEG4这8个引脚。
实现的功能:
每按一个按键都能让蜂鸣器发出一个短暂的声音。

main.c源文件代码如下:
  1. #include "stm32f4xx.h"
  2. #include "main.h"
  3. #include "led.h"
  4. #include "key.h"

  5. int main(void)
  6. {
  7. LED_Configuration();
  8. beep_Configuration();
  9. SysTick_Configuration();
  10. ch452_initial(); //跟按键有关的CH452A芯片初始化
  11. while (1)
  12. {
  13. key_service();
  14. }
  15. }


  16. void SysTick_Configuration(void) //SysTick定时器中断配置
  17. {
  18. if (SysTick_Config(SystemCoreClock / 1000))
  19. {
  20. while (1);
  21. }
  22. }

复制代码

SysTick的定时中断函数如下:
  1. void SysTick_Handler(void)
  2. {

  3. if(1==Gu8VoiceStart)
  4. {

  5. if(Gu16VoiceCnt!=0)
  6. {
  7. Gu16VoiceCnt--;
  8. beep_ON;
  9. }
  10. else
  11. {
  12. beep_OFF;
  13. Gu8VoiceStart=0;
  14. }
  15. }
  16. }
复制代码

key.c的源文件代码如下:
  1. #include "stm32f4xx.h"
  2. #include "key.h"
  3. #include "delay.h"


  4. u8 Gu8KeySec=0;
  5. u16 Gu16VoiceCnt=0;
  6. u8 Gu8VoiceStart=0;


  7. void beep_Configuration(void) //蜂鸣器IO口设置
  8. {

  9. GPIO_InitTypeDef GPIO_InitStructure;
  10. RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOF, ENABLE);

  11. GPIO_InitStructure.GPIO_Pin =GPIO_Pin_8;
  12. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  13. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  14. GPIO_Init(GPIOF, &GPIO_InitStructure);
  15. }

  16. void ch452_initial(void)
  17. {
  18. if(key_board_config())
  19. KEY_INT_Config();
  20. }

  21. void Key_GPIO_Init(void) //按键IO口设置
  22. {
  23. GPIO_InitTypeDef GPIO_InitStructure;
  24. EXTI_InitTypeDef EXTI_InitStructure;

  25. RCC_AHB1PeriphClockCmd(KEY_SDA_GPIO_Clock | KEY_SCL_GPIO_Clock, ENABLE);
  26. RCC_AHB1PeriphClockCmd(KEY_INT_GPIO_Clock, ENABLE);
  27. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  28. GPIO_InitStructure.GPIO_Pin = KEY_SDA_PIN ;
  29. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  30. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  31. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  32. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  33. GPIO_Init(KEY_SDA_GPIO,&GPIO_InitStructure);

  34. GPIO_InitStructure.GPIO_Pin = KEY_SCL_PIN ;
  35. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  36. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  37. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  38. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  39. GPIO_Init(KEY_SCL_GPIO,&GPIO_InitStructure);

  40. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  41. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  42. GPIO_InitStructure.GPIO_Pin = KEY_INT_PIN;
  43. GPIO_Init(KEY_INT_GPIO, &GPIO_InitStructure);

  44. SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOG, EXTI_PinSource6);
  45. EXTI_InitStructure.EXTI_Line = EXTI_Line6;
  46. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  47. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  48. EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  49. EXTI_Init(&EXTI_InitStructure);
  50. }


  51. void KEY_INT_Config(void) //中断配置
  52. {
  53. NVIC_InitTypeDef NVIC_InitStructure;

  54. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  55. NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
  56. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
  57. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  58. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  59. NVIC_Init(&NVIC_InitStructure);
  60. }


  61. void EXTI9_5_IRQHandler(void) //有按键被按下时,中断入口函数
  62. {
  63. if(EXTI_GetITStatus(EXTI_Line6)!= RESET )
  64. {



  65. key_scan(); //按键扫描和处理


  66. EXTI_ClearITPendingBit(EXTI_Line6);
  67. EXTI_ClearFlag(EXTI_Line6);
  68. }
  69. }


  70. void key_scan(void) //按键扫描和处理
  71. {
  72. u8 u8KeyRead;
  73. u8KeyRead = I2C_Read_Byte(0x6F);
  74. switch(u8KeyRead)
  75. {
  76. case 0x7F:
  77. Gu8KeySec=1;
  78. break;
  79. case 0x77:
  80. Gu8KeySec=2;
  81. break;
  82. case 0x6F:
  83. Gu8KeySec=3;
  84. break;
  85. case 0x67:
  86. Gu8KeySec=4;
  87. break;
  88. case 0x7E:
  89. Gu8KeySec=5;
  90. break;
  91. case 0x76:
  92. Gu8KeySec=6;
  93. break;
  94. case 0x6E:
  95. Gu8KeySec=7;
  96. break;
  97. case 0x66:
  98. Gu8KeySec=8;
  99. break;
  100. case 0x7D:
  101. Gu8KeySec=9;
  102. break;
  103. case 0x75:
  104. Gu8KeySec=10;
  105. break;
  106. case 0x6D:
  107. Gu8KeySec=11;
  108. break;
  109. case 0x65:
  110. Gu8KeySec=12;
  111. break;
  112. case 0x7C:
  113. Gu8KeySec=13;
  114. break;
  115. case 0x74:
  116. Gu8KeySec=14;
  117. break;
  118. case 0x6C:
  119. Gu8KeySec=15;
  120. break;
  121. case 0x64:
  122. Gu8KeySec=16;
  123. break;
  124. }

  125. }


  126. void key_service(void) //按键服务程序
  127. {


  128. switch(Gu8KeySec)
  129. {
  130. case 1:

  131. Gu16VoiceCnt=const_voice_short; //让蜂鸣器发出声音,操作的细节在SysTick定时器中断里
  132. Gu8VoiceStart=1;
  133. Gu8KeySec=0;
  134. break;
  135. case 2:

  136. Gu16VoiceCnt=const_voice_short;
  137. Gu8VoiceStart=1;
  138. Gu8KeySec=0;
  139. break;
  140. case 3:

  141. Gu16VoiceCnt=const_voice_short;
  142. Gu8VoiceStart=1;
  143. Gu8KeySec=0;
  144. break;
  145. case 4:

  146. Gu16VoiceCnt=const_voice_short;
  147. Gu8VoiceStart=1;
  148. Gu8KeySec=0;
  149. break;
  150. case 5:

  151. Gu16VoiceCnt=const_voice_short;
  152. Gu8VoiceStart=1;
  153. Gu8KeySec=0;
  154. break;
  155. case 6:

  156. Gu16VoiceCnt=const_voice_short;
  157. Gu8VoiceStart=1;
  158. Gu8KeySec=0;
  159. break;
  160. case 7:

  161. Gu16VoiceCnt=const_voice_short;
  162. Gu8VoiceStart=1;
  163. Gu8KeySec=0;
  164. break;
  165. case 8:

  166. Gu16VoiceCnt=const_voice_short;
  167. Gu8VoiceStart=1;
  168. Gu8KeySec=0;
  169. break;
  170. case 9:

  171. Gu16VoiceCnt=const_voice_short;
  172. Gu8VoiceStart=1;
  173. Gu8KeySec=0;
  174. break;

  175. case 10:

  176. Gu16VoiceCnt=const_voice_short;
  177. Gu8VoiceStart=1;
  178. Gu8KeySec=0;
  179. break;

  180. case 11:

  181. Gu16VoiceCnt=const_voice_short;
  182. Gu8VoiceStart=1;
  183. Gu8KeySec=0;
  184. break;

  185. case 12:

  186. Gu16VoiceCnt=const_voice_short;
  187. Gu8VoiceStart=1;
  188. Gu8KeySec=0;
  189. break;

  190. case 13:

  191. Gu16VoiceCnt=const_voice_short;
  192. Gu8VoiceStart=1;
  193. Gu8KeySec=0;
  194. break;

  195. case 14:

  196. Gu16VoiceCnt=const_voice_short;
  197. Gu8VoiceStart=1;
  198. Gu8KeySec=0;
  199. break;

  200. case 15:

  201. Gu16VoiceCnt=const_voice_short;
  202. Gu8VoiceStart=1;
  203. Gu8KeySec=0;
  204. break;

  205. case 16:

  206. Gu16VoiceCnt=const_voice_short;
  207. Gu8VoiceStart=1;
  208. Gu8KeySec=0;
  209. break;
  210. }

  211. }


  212. void SDA_IN_Config(void)
  213. {
  214. GPIO_InitTypeDef GPIO_InitStructure;
  215. GPIO_InitStructure.GPIO_Pin = KEY_SDA_PIN;
  216. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  217. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  218. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  219. GPIO_Init(KEY_SDA_GPIO,&GPIO_InitStructure);
  220. }

  221. void SDA_OUT_Config(void)
  222. {
  223. GPIO_InitTypeDef GPIO_InitStructure;
  224. GPIO_InitStructure.GPIO_Pin = KEY_SDA_PIN;
  225. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
  226. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  227. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  228. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  229. GPIO_Init(KEY_SDA_GPIO,&GPIO_InitStructure);
  230. }


  231. u8 Get_edition(void)
  232. {
  233. u8 edition_value;

  234. I2C_Write_Byte(0x60,0x40);

  235. edition_value = I2C_Read_Byte(0x61);

  236. if(edition_value==0x20)

  237. return 1;

  238. else

  239. return 0;
  240. }



  241. void I2C_Stop(void)
  242. {
  243. delay(50);
  244. SCL_High;
  245. delay(50);
  246. SDA_High;
  247. delay(50);
  248. }

  249. void I2C_Start(void)
  250. {
  251. SDA_High;
  252. SCL_High;
  253. delay(50);
  254. SDA_Low;
  255. delay(50);
  256. SCL_Low;
  257. }

  258. void data_trans(u8 outdata)
  259. {
  260. u8 i;
  261. for(i=0;i<8;i++)
  262. {
  263. delay(20);
  264. if(outdata & 0x80)
  265. SDA_High;
  266. else
  267. SDA_Low;
  268. delay(30);
  269. SCL_High;
  270. delay(50);
  271. SCL_Low;
  272. outdata=outdata<<1;
  273. }
  274. delay(50);
  275. SDA_IN_Config();
  276. delay(10);
  277. SCL_High;
  278. }

  279. u8 data_receive(void)
  280. {
  281. u8 indata=0x00;
  282. u8 i;

  283. for(i=0;i<8;i++)
  284. {
  285. indata = indata<<1;
  286. delay(50);
  287. SCL_High;
  288. if(KEY_SDA_GPIO->IDR & KEY_SDA_PIN)
  289. indata=indata+1;
  290. delay(50);
  291. SCL_Low;
  292. }
  293. delay(50);
  294. SCL_High;
  295. return indata;
  296. }

  297. void I2C_Write_Byte(u8 reg_addr,u8 data)
  298. {
  299. I2C_Start();
  300. data_trans(reg_addr);
  301. while(ACK_STATE);
  302. delay(50);
  303. SDA_OUT_Config();
  304. SCL_Low;
  305. data_trans(data);
  306. while(ACK_STATE);
  307. delay(50);
  308. SCL_Low;
  309. SDA_OUT_Config();
  310. I2C_Stop();
  311. }

  312. u8 I2C_Read_Byte(u8 reg_addr)
  313. {
  314. u8 temp_data;
  315. I2C_Start();
  316. data_trans(reg_addr);
  317. while(ACK_STATE);
  318. delay(50);
  319. SCL_Low;
  320. temp_data=data_receive();
  321. delay(50);
  322. SDA_OUT_Config();
  323. I2C_Stop();
  324. return (temp_data);
  325. }


  326. u8 key_board_config(void)
  327. {

  328. Key_GPIO_Init();
  329. I2C_Write_Byte(0x6E,0x80);

  330. if(Get_edition())
  331. {
  332. I2C_Write_Byte(0x68,0x22);
  333. }

  334. return (1);

  335. }
复制代码


key.h的头文件代码如下:

  1. #ifndef _KEY_
  2. #define _KEY_

  3. #include "stm32f4xx_gpio.h"

  4. #define const_voice_short 100


  5. #define KEY_SDA_PIN GPIO_Pin_13
  6. #define KEY_SCL_PIN GPIO_Pin_3

  7. #define KEY_SDA_GPIO GPIOC
  8. #define KEY_SDA_GPIO_Clock RCC_AHB1Periph_GPIOC

  9. #define KEY_SCL_GPIO GPIOB
  10. #define KEY_SCL_GPIO_Clock RCC_AHB1Periph_GPIOB

  11. #define KEY_INT_PIN GPIO_Pin_6
  12. #define KEY_INT_GPIO GPIOG
  13. #define KEY_INT_GPIO_Clock RCC_AHB1Periph_GPIOG

  14. #define SDA_High GPIO_SetBits(KEY_SDA_GPIO,KEY_SDA_PIN)
  15. #define SDA_Low GPIO_ResetBits(KEY_SDA_GPIO,KEY_SDA_PIN)
  16. #define SCL_High GPIO_SetBits(KEY_SCL_GPIO,KEY_SCL_PIN)
  17. #define SCL_Low GPIO_ResetBits(KEY_SCL_GPIO,KEY_SCL_PIN)
  18. #define ACK_STATE KEY_SDA_GPIO->IDR & KEY_SDA_PIN

  19. #define beep_OFF GPIO_ResetBits(GPIOF , GPIO_Pin_8)
  20. #define beep_ON GPIO_SetBits(GPIOF , GPIO_Pin_8)

  21. void beep_Configuration(void);
  22. void Key_Init(void);
  23. void KEY_INT_Config(void);
  24. void Key_GPIO_Init(void);
  25. void Delay(__IO uint32_t nTime);
  26. void EXTI9_5_IRQHandler(void);

  27. void SDA_IN_Config(void);
  28. void SDA_OUT_Config(void);
  29. u8 I2C_Read_Byte(u8 reg_addr);
  30. void I2C_Write_Byte(u8 reg_addr,u8 data);
  31. void I2C_Start(void);
  32. void I2C_Stop(void);
  33. u8 data_receive(void);
  34. void data_trans(u8 outdata);

  35. u8 Get_edition(void);
  36. u8 key_board_config(void);
  37. void key_scan(void);
  38. void key_service(void);
  39. void ch452_initial(void);

  40. extern u8 Gu8KeySec;
  41. extern u16 Gu16VoiceCnt;
  42. extern u8 Gu8VoiceStart;

  43. #endif

复制代码

delay.c源文件如下:
  1. #include "stm32f4xx.h"
  2. #include "delay.h"


  3. void delay(unsigned long Delay11_MS)
  4. {
  5. unsigned long Delay11_us;
  6. for(Delay11_us=0;Delay11_us<Delay11_MS;Delay11_us++);
  7. }
复制代码


其它关联度不大的源文件就不再列出。




乐于分享,勇于质疑!
沙发
发表于 2015-7-10 19:13:23 | 只看该作者
鸿哥,为什么你贴出来的代码那么好看,我贴出来的那么丑呢?
乐于分享,勇于质疑!
板凳
 楼主| 发表于 2015-7-11 11:49:51 | 只看该作者
重庆-风雪 发表于 2015-7-10 19:13
鸿哥,为什么你贴出来的代码那么好看,我贴出来的那么丑呢?

贴代码用编辑工具“<>”。
乐于分享,勇于质疑!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )

GMT+8, 2024-4-24 00:08 , Processed in 0.203279 second(s), 17 queries .

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