?? 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 + -