⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 4k.c

📁 针对at91sam7s64芯片实现产生pwm信号
💻 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 + -