📄 4k.c
字号:
/*
*微镜转动一次采集4k的数据
*/
#include "at91sam7s64.h"
#include "lib_at91sam7s64.h"
unsigned int SPI_Rx;
unsigned short int AD_Result[4096],AD_Number;
unsigned int T0RC=0x00000100;
unsigned int T1RC=0x00001000;
unsigned int PWM0_DUTY=0x200;
unsigned char PWM_Frequce=50;
unsigned char *PCrx;
unsigned char PCRX_buff[5];
unsigned char PCRX_state; //接收状态标志,=0为等待接收,=1为正在接收,=2为接收完毕
unsigned char PCRX_timeout;
unsigned char Cammand_state; //命令标志,=0为待机,=1为启动AD,=2传输开始,
#define Idel 0;
#define Start_PWM 1;
#define Start_AD 2;
#define Trans_Data 3;
/*******************************************************************************
SPI读一个字节的数据 Read_Byte_SPI()
*******************************************************************************/
unsigned int Read_Byte_SPI(unsigned int SPI_DATA) //SPI读一个字节的数据
{
*AT91C_SPI_TDR = SPI_DATA;
while((*AT91C_SPI_SR&AT91C_SPI_TXEMPTY) ==0) ; //等待数据接收完成
return (*AT91C_SPI_RDR & 0xffff);
}
void Uart0_Interrupt(void) __irq
{
if(PCRX_state==0) //如果处于等待接受状态//
{
PCrx=PCRX_buff; //接收指针指向接收缓冲//
PCRX_state=1; //接收状态置1//
PCRX_timeout=0; //接收超时置0//
}
if(PCRX_state==1) //如果接收开始//
{
*PCrx++=(*AT91C_US0_RHR&0xff); //指针加一//
PCRX_timeout=0; //接收超时置0/
}
*AT91C_AIC_EOICR = 0x00;
}
void timer0_c_irq_handler(void) __irq //1us
{
unsigned int i;
SPI_Rx =0;
*AT91C_PIOA_CODR=0x00040000; //PIOA18-AD START 输出低电平,开始转换
SPI_Rx=Read_Byte_SPI(0xD000);
*AT91C_PIOA_SODR=0x00040000; //PIOA18-AD START输出高电平,结束转换
if(AD_Number==4096)
{
*AT91C_TC0_CCR = AT91C_TC_CLKDIS; //一次4k数据采样结束,关闭 t0,等待把数据取走
// *AT91C_TC1_CCR = AT91C_TC_SWTRG|AT91C_TC_CLKEN; //打开t1 超时定时器,准备接收新的命
AD_Number=0;
}
else
{
AD_Result[AD_Number++]=SPI_Rx;
}
*AT91C_TC0_RC = T0RC; //RC赋值
i= *AT91C_TC0_SR;
*AT91C_AIC_EOICR = 0x00;
}
//TIMER1作为串口超时计时器
void timer1_c_irq_handler(void) __irq //25ms
{
unsigned int i;
if((*AT91C_PIOA_ODSR&0x000300)==0x000300) //如果PIOA8输出高电平
*AT91C_PIOA_CODR=0x000300; //PIOA8输出低电平
else
*AT91C_PIOA_SODR=0x000300; //PIOA8输出高电平
if(PCRX_state==1) //如果接收开始//
{
if(PCRX_timeout>20) //并且超时20次//
{
PCRX_state=2; //接收成功//
// *AT91C_TC1_CCR =AT91C_TC_CLKDIS; //关闭t1,
}
else PCRX_timeout++; //接收开始但超时<20次,接收超时加一//
}
*AT91C_TC1_RC = T1RC; //定时预设值*/
i=*AT91C_TC1_SR;
*AT91C_AIC_EOICR = 0x00;
}
void Uart_PackgeProce(void)
{
unsigned char i;
if((PCRX_buff[0]==0xff)&&(PCRX_buff[4]==0x55)) //如果首尾数据标准正确
{
switch(PCRX_buff[1]) //命令状态判断
{
case 0: Cammand_state=Idel; break;
case 1: Cammand_state=Start_PWM; break;
case 2: Cammand_state=Start_AD break;
case 3: Cammand_state=Trans_Data; break;
default : break;
}
if((PCRX_buff[2]>0)&&(PCRX_buff[2]<60)) //如果频率数在范围之内
{
PWM_Frequce= PCRX_buff[2];
T0RC= 47923200/(PWM_Frequce*4096*2); //每个微镜周期采集4k的数据
}
}
for(i=0;i<5;i++) //接收缓存清零
PCRX_buff[i]=0;
}
void Uart0_init(void)
{
*AT91C_PMC_PCER = (unsigned int)1<<AT91C_ID_US0; //允许US0口的时钟
*AT91C_PIOA_PDR = AT91C_PIO_PA5 | AT91C_PIO_PA6; //PA4、5设为外设
*AT91C_PIOA_ASR = AT91C_PIO_PA5 | AT91C_PIO_PA6; //PA4、5设为外设A
*AT91C_US0_CR = AT91C_US_RXEN | AT91C_US_TXEN;
*AT91C_US0_MR=AT91C_US_USMODE_NORMAL | /* Normal Mode */
AT91C_US_CLKS_CLOCK | /* Clock = MCK */
AT91C_US_CHRL_8_BITS | /* 8-bit Data */
AT91C_US_PAR_NONE | /* No Parity */
AT91C_US_NBSTOP_1_BIT; /* 1 Stop Bit */
//普通USART模式,主时钟,8字节数据,无效验
*AT91C_US0_BRGR=(unsigned int) (47923200/(9600*16)) ; //波特率9600
*AT91C_US0_IER =AT91C_US_RXRDY ;
AT91C_AIC_SVR[AT91C_ID_US0]=(unsigned int)*Uart0_Interrupt;
*AT91C_AIC_IECR = 1<<AT91C_ID_US0; //打开AIC中断
}
unsigned char putchar (unsigned char ch)
{
while (!((*AT91C_US0_CSR) & AT91C_US_TXRDY));
return (*AT91C_US0_THR = ch);
}
void printf( unsigned char *s)
{
while (*s)
{
putchar(*s);
s++;
}
}
void Sys_init()
{
*AT91C_WDTC_WDMR=AT91C_WDTC_WDDIS; //禁用看门狗
*AT91C_PMC_SCER |= AT91C_PMC_PCK2; //PCK2输出
AT91C_PMC_PCKR[2]=AT91C_PMC_CSS_PLL_CLK|AT91C_PMC_PRES_CLK_2;
*AT91C_PMC_MOR=((AT91C_CKGR_OSCOUNT &(0X06<<8)|AT91C_CKGR_MOSCEN)); //主振荡器使能,指定慢时钟周期乘以8作为主振荡器启动时间
while(!(*AT91C_PMC_SR & AT91C_PMC_MOSCS)); //如果主振荡器稳定
*AT91C_CKGR_PLLR=((AT91C_CKGR_DIV & 9)| //PLL 9分频器输出
(AT91C_CKGR_OSCOUNT & (30<<8))|
(AT91C_CKGR_MUL&(45<<16))); //MUL=45
while(!(*AT91C_PMC_SR & AT91C_PMC_LOCK)) ;
while(!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY)) ;
*AT91C_PMC_MCKR=AT91C_PMC_CSS_PLL_CLK|AT91C_PMC_PRES_CLK_2;//主时钟PLL/2, MCK= 18.432*(45+1)/9
*AT91C_PMC_SCER=11; //使能处理器时钟
while(!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY)) ;
}
//SPI总线初始化//
void SPI_init()
{
*AT91C_PMC_PCER=1<<AT91C_ID_SPI ;
//PIO外设功能时钟始能
*AT91C_PIOA_PDR|=(AT91C_PA12_MISO|AT91C_PA13_MOSI|AT91C_PA14_SPCK|AT91C_PA11_NPCS0);
//PIO使能引脚的外设功能
*AT91C_PIOA_ASR|=(AT91C_PA12_MISO|AT91C_PA13_MOSI|AT91C_PA14_SPCK|AT91C_PA11_NPCS0);
//外设A分配给SPI外设A功能;
*AT91C_SPI_CR|=AT91C_SPI_SPIEN ; //允许SPI口
*AT91C_SPI_MR|=(AT91C_SPI_MSTR|AT91C_SPI_PS_FIXED|AT91C_SPI_MODFDIS|AT91C_SPI_DLYBCS);
//主机模式,不分频,固定片选0,禁止错误检测
*AT91C_SPI_CSR=AT91C_SPI_NCPHA|AT91C_SPI_BITS_16|((unsigned int) 0x02<<8);
//16位数据,传输完成后片选保持,48M/256分频
*AT91C_SPI_IER=AT91C_SPI_TXEMPTY; //TXEMPTY: 发送缓冲器空中断使能
//TDRE: SPI 接收数据寄存器满中断使能
//*AT91C_SPI_IER=AT91C_SPI_RDRF;
// AT91C_AIC_SVR[AT91C_ID_SPI]=(unsigned int)*SPI_irq_handler; //打开AIC中断
//*AT91C_AIC_IECR = 1<<AT91C_ID_SPI;
}
//*******************************************************************************/
// 1uS定时器初始化timer0_init()
// 定时器翻转频率Fout=MCK/(TIMER_CLOCK1 * AT91C_TC0_Rx的值)
//
// TIMER_CLOCK1->MCK/2, TIMER_CLOCK2->MCK/8,TIMER_CLOCK3->MCK/32,
// TIMER_CLOCK4->MCK/128, TIMER_CLOCK5->MCK/1024,
//*******************************************************************************
void timer0_init(void)
{
*AT91C_PMC_PCER = 1<<AT91C_ID_TC0; //允许TC0口的时钟
*AT91C_TC0_CCR = AT91C_TC_CLKDIS; //使能计数时钟
*AT91C_TC0_CMR = AT91C_TC_WAVE|AT91C_TC_WAVESEL_UP_AUTO|AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
*AT91C_TC0_RC = T0RC; //RC赋值
*AT91C_TC0_IER = AT91C_TC_CPCS; //选用RC比较
AT91C_AIC_SMR[AT91C_ID_TC0] =6;
*AT91C_AIC_IECR = 1<<AT91C_ID_TC0; //打开AIC中断
AT91C_AIC_SVR[AT91C_ID_TC0]=(unsigned int)*timer0_c_irq_handler;
//*AT91C_TC0_CCR = 0x04;
}
//*******************************************************************************/
// 25ms定时器初始化timer1_init()
//*******************************************************************************
//
void timer1_init(void)
{
*AT91C_PMC_PCER = 1<<AT91C_ID_TC1; //允许TC1口的时钟
*AT91C_TC1_CCR = AT91C_TC_CLKEN; //使能计数时钟
*AT91C_TC1_CMR = AT91C_TC_WAVE|AT91C_TC_WAVESEL_UP_AUTO|AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
*AT91C_TC1_RC = T1RC;
*AT91C_TC1_IER = AT91C_TC_CPCS;
AT91C_AIC_SMR[AT91C_ID_TC1] =2;
*AT91C_AIC_IECR = 1<<AT91C_ID_TC1; //打开AIC中断
AT91C_AIC_SVR[AT91C_ID_TC1]=(unsigned int)*timer1_c_irq_handler;
*AT91C_TC1_CCR = 0x04;
}
//*******************************************************************************/
// PWM_Init()
// PWM0翻转频率Fout=MCK/(PWM0_CLK_SEL* PWM0_PRD的值)
// 分频因子PWM0_CLK_SEL:1,2,4,8,16,32,64,128,256,512,1024
//*******************************************************************************
void PWM_Init(void)
{
*AT91C_PMC_PCER = 1<<AT91C_ID_PWMC; //允许PWM的时钟
*AT91C_PWMC_MR = 0x0a080a08; //模式寄存器,MCK/1024,之后再8分频
*AT91C_PWMC_CH0_CDTYR= PWM0_DUTY; // (PWMC_CH0) Channel Duty Cycle Register
*AT91C_PWMC_CH0_CMR = 0x09; //模式寄存器,MCK/512
}
void PWM_Start(unsigned char Frequce)
{
unsigned int i;
i= 92000/Frequce ;
*AT91C_PWMC_CH0_CPRDR=i; // (PWMC_CH0) Channel Period Register
*AT91C_PWMC_CH0_CDTYR=i/2; //50%占空比
*AT91C_PWMC_ENA = 0x01; // 使能PWM0
}
void AD_Start(void)
{
*AT91C_TC0_CCR =AT91C_TC_SWTRG|AT91C_TC_CLKEN;
}
/****************************************************************************
将数据缓存区的AD数据通过串口发送到PC
*******************************************************************************/
void Trans_data(void)
{
unsigned short int Tx_char,i;
unsigned char Tx_char_H,Tx_char_L;
for(i=0;i<4095;i++)
{
Tx_char=AD_Result[i];
Tx_char_H=(unsigned char)(Tx_char>>8);
Tx_char_L=(unsigned char)(Tx_char&0xff);
putchar(Tx_char_H);
putchar(Tx_char_L);
}
}
void main(void)
{
Sys_init();
SPI_init();
timer1_init();
timer0_init();
PWM_Init();
Uart0_init();
*AT91C_PIOA_PER=0x040380; //PIOA0-2作为I/O使用
*AT91C_PIOA_OER=0x040380; //PIOA0-2输出使能
*AT91C_PIOA_PDR|= 0x80800000;
*AT91C_PIOA_BSR|= 0x80800000; //PA31输出PCK2,PA23--PWM0
while(1)
{
if(PCRX_state==2) //串口命令处理
{
Uart_PackgeProce();
PCRX_state=0;
switch(Cammand_state)
{
case 1:
{
PWM_Start(PWM_Frequce); //打开t0,微镜转动一次取4k数据
break;
}
case 2:
{
AD_Start();
break;
}
case 3:
{
Trans_data();
break;
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -