【ST学习小组】STM32F103的CAN 通信之从控器部分

来源:互联网 发布:双系统linux安装教程 编辑:程序博客网 时间:2024/04/30 21:45
【ST学习小组】STM32F103的CAN 通信之主控器

 

http://www.eefocus.com/bbs/article_244_380394.html

 http://www.stmcu.org/bbs/article_244_380402.html

下面是从控器部分代码:

main.c部分代码

/******************** (C) COPYRIGHT *******************************************

* File Name          : main.c

* Author             : MJQ 

* Version            : V1.0

* 环境  : mdk423-固件库V3.5版本、

* 芯片  : STM32F103VB-ALIENTEK开发板 

* Date               : 2012-04-12

* Description        : 外部中断函数,按key0 led1灭串口发送0xaa、按key1 led2灭串口发送0x55、

   接收到电脑发送数据或按PA0时,led1、led2全亮

* 定义  :        LED1-------PA8

LED2-------PD2

KEY0-------PA13

KEY1-------PA15

TXD1-------PA9

RXD1-------PA10

EXTI0------PA0

********************************************************************************/

/*---------------------Includes------------------------------------------------*/

#include "stm32f10x.h" 

#include "misc.h"

#include "led.h"

#include "key.h"

#include "usart.h"

//#include "exti.h"

#include "can.h"

 

void RCC_Configuration(void);  

void Delay(__IO uint32_t nCount);

 

//___________________Global Variable declare________

u8 CAN_TransmitDataBuf[8];

u8 ADC_num=0;

u16 ADC_Data0[10];

u16 ADC_Data1[10];

u16 ADC_Data2[10];

u16 ADC_Data3[10];

 

//______________________________________________

 

 

//___________________________ADC modue__________

 

void  Adc_Init(void)

{    

//先初始化IO口

  RCC->APB2ENR|=1<<2;    //使能PORTA口时钟 

GPIOA->CRL&=0XFFFF0000;//PA0 1 2 3 anolog输入

//通道10/11设置 

RCC->APB2ENR|=1<<9;    //ADC1时钟使能  

RCC->APB2RSTR|=1<<9;   //ADC1复位

RCC->APB2RSTR&=~(1<<9);//复位结束    

RCC->CFGR&=~(3<<14);   //分频因子清零

//SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!

//否则将导致ADC准确度下降! 

RCC->CFGR|=2<<14;       

 

ADC1->CR1&=0XF0FFFF;   //工作模式清零

ADC1->CR1|=0<<16;      //独立工作模式  

ADC1->CR1&=~(1<<8);    //非扫描模式  

ADC1->CR2&=~(1<<1);    //单次转换模式

ADC1->CR2&=~(7<<17);   

ADC1->CR2|=7<<17;   //软件控制转换  

ADC1->CR2|=1<<20;      //使用用外部触发(SWSTART)!!!必须使用一个事件来触发

ADC1->CR2&=~(1<<11);   //右对齐 

ADC1->SQR1&=~(0XF<<20);

ADC1->SQR1&=0<<20;   

//设置通道0~3的采样时间

ADC1->SMPR2&=0XFFFFF000;//通道0,1,2,3采样时间清空  

ADC1->SMPR2|=7<<9;      //通道3  239.5周期,提高采样时间可以提高精确度 

ADC1->SMPR2|=7<<6;      //通道2  239.5周期,提高采样时间可以提高精确度 

ADC1->SMPR2|=7<<3;      //通道1  239.5周期,提高采样时间可以提高精确度 

ADC1->SMPR2|=7<<0;      //通道0  239.5周期,提高采样时间可以提高精确度 

 

ADC1->CR2|=1<<0;    //开启AD转换器 

ADC1->CR2|=1<<3;        //使能复位校准  

while(ADC1->CR2&1<<3);  //等待校准结束  

    //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。  

ADC1->CR2|=1<<2;        //开启AD校准   

while(ADC1->CR2&1<<2);  //等待校准结束

//该位由软件设置以开始校准,并在校准结束时由硬件清除  

}   

//获得ADC值

//ch:通道值 0~3

u16 Get_Adc(u8 ch)   

{

//设置转换序列   

ADC1->SQR3&=0XFFFFFFE0;//规则序列1 通道ch

ADC1->SQR3|=ch;      

ADC1->CR2|=1<<22;       //启动规则转换通道 

while(!(ADC1->SR&1<<1));//等待转换结束    

return ADC1->DR;//返回adc值

}

 

 

 

 

 

 

//_________________________________________________

 

 

 

 

//_____________________ADC 采样值发送________

void ADC_TransmitByCan(u16 Data_CH1,u16 Data_CH2,u16 Data_CH3)

{

}

 

 

//////////////////////////////////////////////////////////////////////////////////   

//int i=0; 

u32 GetP(u16 *ADC_Point)

{

u32 ADC_sum=0;

     u16 Max=0;

    u16 Min=0xFF;

u8 index=0;

 

for(index=0;index<9;index++)

{

if( (*(ADC_Point+index)) >Max )

{

Max=(*(ADC_Point+index));

}

if( (*(ADC_Point+index)) <Min)

{

Min=(*(ADC_Point+index));

}

ADC_sum+=(u32) ((*(ADC_Point+index)));

}

ADC_sum=(ADC_sum-Max-Min)/8;

return ADC_sum;

}

 

 

 

 

 

//定时器3中断服务程序  

void TIM3_IRQHandler(void)

      

    

  u32 ADC0_sum=0;

  u32 ADC1_sum=0;

  u32 ADC2_sum=0;

if(TIM3->SR&0X0001)//溢出中断

{

   

   ADC_Data1[ADC_num]=Get_Adc(ADC_Channel_1);

   ADC_Data2[ADC_num]=Get_Adc(ADC_Channel_2);

           ADC_Data0[ADC_num]=Get_Adc(ADC_Channel_0);

            ADC_num++;

  if (ADC_num>=10)

  {    

       ADC0_sum=GetP(ADC_Data0);

 ADC1_sum=GetP(ADC_Data1);

 ADC2_sum=GetP(ADC_Data2);

CAN_TransmitDataBuf[1]=(ADC0_sum&0x00ff);

 CAN_TransmitDataBuf[0]=((ADC0_sum>>8)&0x00ff);

CAN_TransmitDataBuf[3]=(ADC1_sum&0x00ff);

 CAN_TransmitDataBuf[2]=((ADC1_sum>>8)&0x00ff);

CAN_TransmitDataBuf[5]=(ADC2_sum&0x00ff);

 CAN_TransmitDataBuf[4]=((ADC2_sum>>8)&0x00ff);

  CAN_TransmitData(6,CAN_TransmitDataBuf,0xAAAA);

  }

                 

}   

TIM3->SR&=~(1<<0);//清除中断标志位   

}

//通用定时器中断初始化

//这里时钟选择为APB1的2倍,而APB1为36M

//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器3!

 

void Timer_init(u16 arr,u16 psc)

{

 

NVIC_InitTypeDef NVIC_InitStructure;

RCC->APB1ENR|=1<<1;//TIM3时钟使能    

  TIM3->ARR=arr;  //设定计数器自动重装值//刚好1ms    

TIM3->PSC=psc;  //预分频器7200,得到10Khz的计数时钟

//这两个东东要同时设置才可以使用中断

TIM3->DIER|=1<<0;   //允许更新中断

TIM3->DIER|=1<<6;   //允许触发中断   

TIM3->CR1|=0x01;    //使能定时器3 

 

  /* Configure the NVIC Preemption Priority Bits */  

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);   

  

  /* Enable the USART1 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;     //设置串口中断

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

 

//_______________________________________________

int main(void)

{  

  RCC_Configuration();  //系统时钟配置 

  //LED_GPIO_Config();    //led配置

  KEY_GPIO_Config();    //按键配置

  //USART_Init_Config();  //串口配置

//  EXTI_Init_Config();

  Adc_Init();

  CAN_Init_Config();

  Timer_init(50,6400);

  while (1)

  {

LED1_ON;

LED2_ON;

Delay(0xFFFFF);

  Delay(0xFFFFF);

 

  }

}

void RCC_Configuration(void)

{   

  /* Setup the microcontroller system. Initialize the Embedded Flash Interface,  

     initialize the PLL and update the SystemFrequency variable. */

  SystemInit();  

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB,ENABLE);   //打开重映射时钟

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* GPIOA clock enable */

//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /* GPIOB clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);   /* CAN Periph clock enable */

}

 

 

void Delay(__IO uint32_t nCount)

{

   for(; nCount != 0; nCount--);

}

 

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *   where the assert_param error has occurred.

  * @param file: pointer to the source file name

  * @param line: assert_param error line source number

  * @retval : None

  */

 

 

 

void assert_failed(uint8_t* file, uint32_t line)

  /* User can add his own implementation to report the file name and line number,

     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

 

  /* Infinite loop */

  while (1)

  {

  }

}

#endif

 

/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

 

 CAN 部分代码

 

#include "can.h"

 
u16 ret;
/******************CAN1中断配置函数*********************************************/
//优先级:0
//中断服务程序:USB_LP_CAN1_RX0_IRQn------stm32f10x_it.
void CAN_NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
 
  /* Enable CAN1 RX0 interrupt IRQ channel */
  NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
/******************CAN1端口配置函数*********************************************/
//引脚:CAN1RX-PA8、CAN1Tx-PB8
//说明:开启端口B的时钟、CAN1的时钟
void CAN_GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
 
  /* Configure CAN pin: RX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  /* Configure CAN pin: TX */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
     /*端口重映射到PB8、PB9上*/
 
 // GPIO_PinRemapConfig(GPIO_Remap2_CAN1, ENABLE);        //配置CAN总线为从映射
 
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);   /* CAN Periph clock enable */
 
}
 
/******************CAN1查询接受配置函数*****************************************/
//波特率:SJW-1tq、BS1-8tq、BS2-7tq、Prescaler-5;
//
u8 CAN_Polling(void)
{
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
  CanTxMsg TxMessage;
  CanRxMsg RxMessage;
  uint32_t i = 0;
  uint8_t TransmitMailbox = 0;
 
  /* CAN register init */
  CAN_DeInit(CAN1);
  CAN_StructInit(&CAN_InitStructure);
 
  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM=DISABLE;
  CAN_InitStructure.CAN_ABOM=DISABLE;
  CAN_InitStructure.CAN_AWUM=DISABLE;
  CAN_InitStructure.CAN_NART=DISABLE;
  CAN_InitStructure.CAN_RFLM=DISABLE;
  CAN_InitStructure.CAN_TXFP=DISABLE;
  CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
  CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler=5;
  CAN_Init(CAN1, &CAN_InitStructure);
 
  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber=0;
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);
 
  /* transmit */
  TxMessage.StdId=0x11;
  TxMessage.RTR=CAN_RTR_DATA;
  TxMessage.IDE=CAN_ID_STD;
  TxMessage.DLC=2;
  TxMessage.Data[0]=0xAA;
  TxMessage.Data[1]=0xAA;
 
  TransmitMailbox=CAN_Transmit(CAN1, &TxMessage);
  i = 0;
  while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFF))
  {
    i++;
  }
 
  i = 0;
  while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFF))
  {
    i++;
  }
 
  /* receive */
  RxMessage.StdId=0x00;
  RxMessage.IDE=CAN_ID_STD;
  RxMessage.DLC=0;
  RxMessage.Data[0]=0x00;
  RxMessage.Data[1]=0x00;
  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
 
  if( (RxMessage.StdId!=0x11)|(RxMessage.StdId!=0x12) )
  {
    return 1;  
  }
 
  if (RxMessage.IDE!=CAN_ID_STD)
  {
    return 1;
  }
 
  if (RxMessage.DLC!=2)
  {
    return 1;  
  }
 
  if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0xCAFE)
  {
    return 1;
  }
  
  return 0; /* Test Passed */
}
/******************CAN1中断接受配置函数*****************************************/
//波特率:SJW-1tq、BS1-8tq、BS2-7tq、Prescaler-5;
//
void  CAN_Interrupt(void)
{
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
 
  /* CAN register init */
  CAN_DeInit(CAN1);
  CAN_StructInit(&CAN_InitStructure);
 
  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM=DISABLE;
  CAN_InitStructure.CAN_ABOM=DISABLE;
  CAN_InitStructure.CAN_AWUM=DISABLE;
  CAN_InitStructure.CAN_NART=DISABLE;
  CAN_InitStructure.CAN_RFLM=DISABLE;
  CAN_InitStructure.CAN_TXFP=DISABLE;
  CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;//Normal 
  CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
  CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;
  CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler=1;
  CAN_Init(CAN1, &CAN_InitStructure);
 
  /* CAN filter init */
  CAN_FilterInitStructure.CAN_FilterNumber=1;
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;
  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);
 
  /* CAN FIFO0 message pending interrupt enable */ 
  CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //CAN 中断使能
 
 
}
 
/******************CAN1数据传送函数*******************************************/
//
//
void CAN_TransmitData(u8 DataLength,u8 *Data_Buf,u32 ID)  /* transmit 1 message */
{
  CanTxMsg TxMessage;
  u8 CAN_Transmitindex=0;
  TxMessage.StdId=ID;
  TxMessage.ExtId=ID;
  TxMessage.IDE=CAN_ID_EXT;
  TxMessage.RTR=CAN_RTR_DATA;
  //_______________Set Data length _________________
  TxMessage.DLC=DataLength;
  for(CAN_Transmitindex=0;CAN_Transmitindex<DataLength;CAN_Transmitindex++)
   {
    TxMessage.Data[CAN_Transmitindex]=Data_Buf[CAN_Transmitindex];
   }
  
  //_____________________________________________
  CAN_Transmit(CAN1, &TxMessage);
}
 
void CAN_Init_Config(void)
{
  CAN_NVIC_Configuration(); //中断配置
  CAN_GPIO_Configuration(); //端口配置
  CAN_Interrupt();  //中断接受配置
 
}
 

0 0