//古道热肠U盘开发板--AD驱动//主办单位:www.21ic.com//项目负责人:古道热肠//作者邮箱:xg_2004_sy@126.com//Blog : http://blog.21ic.com/user1/4538/index.html//完成日期:2008-12-02//备注: 开发板上AD4-AD7为有效AD入口#include <AT91SAM7S64.H> /* AT91SAM7S64 definitions */#include <lib_AT91SAM7s64.h>#include <string.h>#include <stdio.h>#include "..Board.h"#include "DriverLCD_Nokia5110.h"#include "DriverBeep.h"#include "DriverTwi.h"#include "DriverTimer.h"#include "Serial.h"#include "APIComm.h"//初始化硬件为AD模块服务void ADC_Init(){ AT91F_ADC_SoftReset(AT91C_BASE_ADC); //Hradware triggers are disabled. Starting a conversion is only possible by software //8-bit ,set adc clock,the startup time,sample and holding time. AT91F_ADC_CfgModeReg(AT91C_BASE_ADC,AT91C_ADC_TRGEN_DIS | AT91C_ADC_LOWRES_10_BIT | AT91C_ADC_SLEEP_NORMAL_MODE | AT91C_ADC_PRESCAL | AT91C_ADC_STARTUP | AT91C_ADC_SHTIM); AT91F_ADC_EnableChannel(AT91C_BASE_ADC,AT91C_ADC_CH4 | AT91C_ADC_CH5 | AT91C_ADC_CH6 | AT91C_ADC_CH7);// AT91F_ADC_StartConversion(AT91C_BASE_ADC); `}//等待AD转换结束//返回:true 表示读取到转换结束标志符,属转换正常结束// false 表示超时退出,功能出错//备注:根据文档介绍:转换时间最大值为2usbool ADC_WaitEnd(void){ uint uiReadValue; uint uiDelayCount; //10uS计数值的倍数 bool bReturnValue; bReturnValue = false; uiDelayCount = 0; Timer_Start(); //开启定时器 while(uiDelayCount<2) { uiDelayCount = GetTimerCount(); uiReadValue = AT91F_ADC_GetStatus(AT91C_BASE_ADC); if((uiReadValue & 0x000000f0) == 0x000000f0) //仅启用了CH4-CH7通道 { bReturnValue = true; break; } } return(bReturnValue);}void ADC_Start(void){ AT91F_ADC_StartConversion(AT91C_BASE_ADC);}//读取AD转换通道的值,入口参数,AD通道号索引,返回与通道号对应的AD值uint ADC_ReadValue(uchar ucChannelIndex){ uint uiReadValue; switch(ucChannelIndex) { case AT91C_ADC_CH4: uiReadValue = AT91F_ADC_GetConvertedDataCH4(AT91C_BASE_ADC); break; case AT91C_ADC_CH5: uiReadValue = AT91F_ADC_GetConvertedDataCH5(AT91C_BASE_ADC); break; case AT91C_ADC_CH6: uiReadValue = AT91F_ADC_GetConvertedDataCH6(AT91C_BASE_ADC); break; case AT91C_ADC_CH7: uiReadValue = AT91F_ADC_GetConvertedDataCH7(AT91C_BASE_ADC); break; default: uiReadValue = 0; break; } return(uiReadValue);}void TestAD(void){ uint uiReadADValue; uchar ucDispDataBuff[16]; LCD_Clear(); LCD_ShowString(0,0," Test AD"); ADC_Init(); while(1) { ComShowString(c_COM1,"Start AD Convert"); ADC_Start(); ADC_WaitEnd(); ComShowString(c_COM1,"AD Convert Complete"); uiReadADValue = ADC_ReadValue(AT91C_ADC_CH4); sprintf(ucDispDataBuff,"CH4 AD Value is:%4d",uiReadADValue); ComShowString(c_COM1,ucDispDataBuff); LCD_ShowString(0,1,ucDispDataBuff); uiReadADValue = ADC_ReadValue(AT91C_ADC_CH5); sprintf(ucDispDataBuff,"CH5 AD Value is:%4d",uiReadADValue); ComShowString(c_COM1,ucDispDataBuff);// LCD_ShowString(0,1,ucDispDataBuff); uiReadADValue = ADC_ReadValue(AT91C_ADC_CH6); sprintf(ucDispDataBuff,"CH6 AD Value is:%4d",uiReadADValue); ComShowString(c_COM1,ucDispDataBuff);// LCD_ShowString(0,1,ucDispDataBuff); uiReadADValue = ADC_ReadValue(AT91C_ADC_CH7); sprintf(ucDispDataBuff,"CH7 AD Value is:%4d",uiReadADValue); ComShowString(c_COM1,ucDispDataBuff); LCD_ShowString(0,3,ucDispDataBuff); Delay(1); }}enum KeyV { KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_NONE, KEY_ESC, KEY_UP, KEY_OK };const enum KeyV Ktab[] = {KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_NONE, KEY_ESC, KEY_UP,KEY_OK};enum KeyV Read_KeyValue(void) { uchar uci; uint uiReadADCValue; enum KeyV enuKeyReturnValue; const unsigned short KeyTable[] ={ 0, 100, 260, 390, 470, 560, 690, 1023};// ADC_Start(); //由于上一次读取结束时启动了AD转换,所以直接等转换结束后读AD值即可 if(ADC_WaitEnd()) { uiReadADCValue = ADC_ReadValue(AT91C_ADC_CH4); for(uci=0;uci<7;uci++) { if(( KeyTable[uci] <= uiReadADCValue) && (uiReadADCValue < KeyTable[uci+1] ) ) { enuKeyReturnValue = Ktab[uci]; break; } } } else { enuKeyReturnValue = KEY_NONE; } //读取完当前的AD值后,再次启动转换过程 ADC_Start(); return enuKeyReturnValue;}enum KeyV ReadKey(void) { static int KeyCount=0; static enum KeyV preKey=KEY_NONE; //存放前一次按键的值 enum KeyV CurrentKeyValue; CurrentKeyValue = Read_KeyValue(); if(CurrentKeyValue == preKey) { KeyCount++; //防抖动处理 if(KeyCount > 10) //重复检查次数为10次,完全相符,认为按键有效 { KeyCount=0; return CurrentKeyValue; } } else { KeyCount=0; } preKey = CurrentKeyValue; return KEY_NONE;}bool KbHit(void){ enum KeyV ucReadKeyValue; ucReadKeyValue = Read_KeyValue(); if(ucReadKeyValue != KEY_NONE) { return(true); } else { return(false); }}//读取按键值,无阻塞,读完后没有等待按键释放就返回主调函数enum KeyV KbGet(void){ enum KeyV ucKeyValue; uchar ucCount; ucCount= 30; while(ucCount--) { ucKeyValue = ReadKey(); if(ucKeyValue != KEY_NONE) { break; } Delay(1); } return ucKeyValue;}void TestAD_KeyBoard(void){ uchar uci; enum KeyV ucKeyValue;// init_timer(); LCD_Clear(); LCD_ShowString(0,0,"Test AD KBD"); ADC_Init(); //初始化AD是必须执行的操作 //启动一次转换过程,初始化AD模块的读取、启动的循环。 ADC_Start(); Delay(1); while(1) { if(KbHit()) { ComShowString(c_COM1,"Find Key Press"); ucKeyValue = KbGet(); switch(ucKeyValue) { case KEY_ESC: LCD_ShowString(0,2,"Esc Press"); break; case KEY_UP: LCD_ShowString(0,2,"UP Press"); break; case KEY_OK: LCD_ShowString(0,2,"OK Press"); break; case KEY_LEFT: LCD_ShowString(0,2,"LEFT Press"); break; case KEY_DOWN: LCD_ShowString(0,2,"Down Press"); break; case KEY_RIGHT: LCD_ShowString(0,2,"Right Press"); break; default: LCD_ShowString(0,2,"Err!"); break; } //等待按键释放。 while(KbHit()) { // BeepShort(); Delay(1); } } Delay(1); }} |