ARM&WINCE 多通道数据采集驱动实现思路(求高手指点)
来源:互联网 发布:求二叉树的高度算法 编辑:程序博客网 时间:2024/04/29 22:10
本人要编一个多通道数据采集的驱动程序,硬件采用S3C2410A,操作系统是wince,开发工具是PB。第一次接触这些东西,思路有些乱:
数据采集的频率由S3C2410A自带的PWM Timer实现,通过设置PMW寄存器的预分频值、分频值、TCNTB0, TCMPB0,输出一定频率和脉宽的波形,在脉宽的下降沿触发中断,该中断触发线程,将中断与事件关联,实现AD转换。在调用的AD转换函数中实现采样数据读取,放入缓存,更改采样通道的设置。
在ADC_Init()中应用VirtualAlloc()和VirtualCopy()完成物理地址映射成虚拟地址,需要该操作的寄存器有PWM、ADC、GPIO,不确定是否涉及INT。线程函数也放在这里。
DWORD ADC_Init(DWORD dwcontext)
{
DWORD IDThread;
RETAILMSG( 1, (TEXT("Initialing pADCIOreg!/r/n")));
//分配空间
pADCIOreg = ( ADCreg * )VirtualAlloc( 0, sizeof(ADCreg), MEM_RESERVE, PAGE_NOACCESS );
if( !pADCIOreg )
{
RETAILMSG( 1, (TEXT("Unable to alloc memory for ADCIOreg!/r/n")));
return NULL;
}
if( !VirtualCopy((PVOID)pADCIOreg, (PVOID)(ADC_BASE), sizeof(ADCreg),
PAGE_READWRITE | PAGE_NOCACHE ))
{
RETAILMSG(1, (TEXT("For ADCIOreg, virtual copy failed!/r/n")));
return NULL;
}
pPWMIOreg = ( PWMreg * )VirtualAlloc( 0, sizeof(PWMreg), MEM_RESERVE, PAGE_NOACCESS ); //PWMreg,结构体,定义在s2410.h中
if( !pPWMIOreg )
{
RETAILMSG( 1, (TEXT("Unable to alloc memory for PWMIOreg!/r/n")));
return NULL;
}
if( !VirtualCopy((PVOID)pPWMIOreg, (PVOID)(PWM_BASE), sizeof(PWMreg),
PAGE_READWRITE | PAGE_NOCACHE ))
{
RETAILMSG(1, (TEXT("For PWMIOreg, virtual copy failed!/r/n")));
return NULL;
}
pIOPIOreg = ( IOPreg * )VirtualAlloc( 0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS );
if( !pIOPIOreg )
{
RETAILMSG( 1, (TEXT("Unable to alloc memory for IOPIOreg!/r/n")));
return NULL;
}
if( !VirtualCopy((PVOID)pIOPIOreg, (PVOID)(IOP_BASE), sizeof(IOPreg),
PAGE_READWRITE | PAGE_NOCACHE ))
{
RETAILMSG(1, (TEXT("For IOPIOreg, virtual copy failed!/r/n")));
return NULL;
}
pINTIOreg = ( INTreg * )VirtualAlloc( 0, sizeof(INTreg), MEM_RESERVE, PAGE_NOACCESS ); ???????????????????????????????
if( !pINTIOreg )
{
RETAILMSG( 1, (TEXT("Unable to alloc memory for INTIOreg!/r/n")));
return NULL;
}
if( !VirtualCopy((PVOID)pINTIOreg, (PVOID)(INT_BASE), sizeof(INTreg),
PAGE_READWRITE | PAGE_NOCACHE ))
{
RETAILMSG(1, (TEXT("For INTIOreg, virtual copy failed!/r/n")));
return NULL;
}
if(!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,&g_ADCIrq,sizeof(UINT32),&g_ADCIrq,sizeof(UINT32),NULL)) //在底层调用OAL层实现的OEMIoContorl函数
{
RETAILMSG(1,(TEXT("ERROR:EINTKey:Failed to request sysintr value for Timer interrupt./r/n")));
return(0);
}
RETAILMSG(1,(TEXT("INFO:EINTKey:Mapped Irq 0x%x to SysIntr 0x%x./r/n"),g_ADCIrq,g_ADCSysIntr));
gADCIntrThread=CreateThread(0,0,(LPTHREAD_START_ROUTINE)ADCTIMER_IntrThread,0,0,&IDThread);
if(gADCIntrThread==NULL)
{
RETAILMSG(1,(TEXT(":::ADC_Init:CreateThread() Fail./r/n")));
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR,&g_ADCSysIntr,sizeof(UINT32),NULL,0,NULL);
return 0;
}
gADCEvent[0]=CreateEvent(NULL,FALSE,FALSE,NULL); //创建两个事件
gADCEvent[1]=CreateEvent(NULL,FALSE,FALSE,NULL);
RETAILMSG(1,(TEXT(":::ADC_Init Successfully!/r/n")));
return (DWORD)1;
}
DWORD ADCTIMER_IntrThread(PVOID pArg) //中断服务线程,进行定时器中断时的中断处理
{
DWORD ret;
gWaitEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
if(!(InterruptInitialize(g_ADCSysIntr,gWaitEvent,0,0))) //(1)IST使用InterruptInitialize注册自己,将一个中断和一个事件相关联 ???????????????????????????????
{
RETAILMSG(1,(TEXT("ERROR:ADCTIMER:InterruptInitialize failed./r/n")));
CloseHandle(gWaitEvent);
return 0;
}
while(1)
{
ret=WaitForSingleObject(gWaitEvent,INFINITE); //(2)等待中断请求。线程等待,INFINITE: 无限期等待
if((ret==WAIT_OBJECT_0)&&(g_KillIST==FALSE))
{
SetEvent(gADCEvent[0]);
RETAILMSG(1,(TEXT(":::it's time to ad convert!/r/n")));
}
else
{
CloseHandle(gWaitEvent);
RETAILMSG(1,(TEXT(":::ADCTIMER_IntrThread exit!/r/n")));
return 0;
}
InterruptDone(g_ADCSysIntr);
}
return 1;
}
采样相关的函数主要在ADC_IOControl()中实现。启动AD转换部分不太懂。
BOOL ADC_IOControl(volatile ADCreg* pADCIOreg,DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,
PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut )
{
int iDigiValue = 0;
BOOL bErr = FALSE;
DWORD ret;
switch(dwCode)
{
case IOCTL_PWM_SET_PRESCALER:
if (dwLenIn >= 2) /* 需要2个字节缓冲区 */
{
PWM_SetPrescaler(pBufIn[0], pBufIn[1]);//参一:定时器号,参二:预分频值
bErr = TRUE;
}
break;
case IOCTL_PWM_SET_DIVIDER:
if (dwLenIn >= 2) /* 需要2个字节缓冲区 */
bErr = PWM_SetDivider(pBufIn[0], pBufIn[1]);
// 设置分频值 (定时器编号, 分频值)
break;
case IOCTL_PWM_START: //设置采样率(即:pwm波形频率及占空比)
if (dwLenIn >= 3) /* 需要3个字缓冲区 */
{
DWORD t_num = *((DWORD *)pBufIn);
DWORD cycle = *((DWORD *)(pBufIn + 4));
DWORD duty = *((DWORD *)(pBufIn + 8));
// pINTIOreg->rINTMSK&=~(0x1<<10);//不屏蔽timer0的中断,即开timer0的中断
bErr = PWM_StartPWM(t_num, cycle, duty);//定时器号,TCNTB value,TCMPB value
}
break;
case IOCTL_PWM_GET_FREQUENCY:
if ((dwLenIn >= 0) && (dwLenOut > 0))
{
DWORD t_num = *((DWORD *)pBufIn);
bErr = PWM_GetFrequency(t_num, (DWORD *)pBufOut);
*pdwActualOut = 1;
}
break;
case IOCTL_SET_UP:
{
ret=WaitForMultipleObjects(2,gADCEvent,FALSE,INFINITE); //两个同步对象,gADCEvent:指向包含的所有的同步对象,FALSE:只要一个线程处于有信号状态,线程就被唤醒而继续运行。等待时间无限期
if(ret==WAIT_OBJECT_0)
{
ResetEvent(gADCEvent[0]);
//////////????????????????????????????????
//////////?????????????????????????????
/////////////////启动ad
iDigiValue = Read_Adc( pADCIOreg,*pBufIn);
*( int* )pBufOut = iDigiValue;
}
else if(ret==(WAIT_OBJECT_0+1))
{
ResetEvent(gADCEvent[1]);
}
}
break;
default:
break;
}
}
int Read_Adc( volatile ADCreg* pADCIOreg,int ch )
{
RETAILMSG(1, (TEXT("channel:%d/r/n")),ch);
pADCIOreg->rADCCON = (1<<14)|(ch<<3)|(19<<6); // setup channel (19<<6)是设置你的分频值的,19是根据你的采样频率来设置的。
//pADCIOreg->rADCCON |= 0<<3; // setup channel
pADCIOreg->rADCCON |= 0x1; // start adc
while(pADCIOreg->rADCCON & 0x1); //check if Enable_start is low
while(!(pADCIOreg->rADCCON & 0x8000)); //check if End of Conversion flag is high
return ( (int)pADCIOreg->rADCDAT0 & 0x3ff ); //return the digital value
}
望高手帮忙整理一下思路。不胜感激!
- ARM&WINCE 多通道数据采集驱动实现思路(求高手指点)
- 基于ARM的多通道数据采集
- 求高手指点(问题比较罕见)
- 求高手指点
- 求高手指点
- 求高手指点
- 菜鸟求高手指点
- 求高手指点
- 求高手指点
- 求高手指点!!!!
- 求高手指点
- stm32adc多通道数据采集
- stm32adc多通道数据采集
- 求高手指点手机请求网络数据知识
- 求高手指点母函数
- 求高手指点母函数
- 初学多线程,求高手指点
- 几道面试题,求高手指点
- c++中const的用法
- 希望能给我时间学习
- HTTP 头信息详细解释
- ADO.NET_第五篇_DataTable_03Copy/Clone
- 股市的逻辑-201006-2
- ARM&WINCE 多通道数据采集驱动实现思路(求高手指点)
- ADO.NET_第五篇_DataTable_04Merge
- 嵌入式 linux 智能设备应用中 web 支持的实现(二)
- ADO.NET_第五篇_DataTable_05Select
- pplication Fundamentals——应用程序基础知识
- ADO.NET_第五篇_DataTable_06Compute
- 转:优秀程序员的45个习惯
- ADO.NET_第五篇_DataTable_07Relations
- ADO.NET_第五篇_DataTable_08DataView