반응형

https://youtube.com/live/zxJ_ntNADKc

[STM32#30] CAN통신으로 각종 센서값을 전송하고 자동차에서 사용하는 OBD2 프로토콜을 간단하게 모방해보기!(녹칸다 내맘대로 STM32)

심심한녹칸다의 내맘대로 STM32시리즈이다!

STM32시리즈의 모든 자료는 구글 슬라이드에 작성하고 모두에게 공유되어있음!
https://docs.google.com/presentation/d/1myA5iYbjuKsLWLqtRLKAiRfwUwvqB1d1RGjiMIIgp3I/edit?slide=id.g3be1268f534_1_233#slide=id.g3be1268f534_1_233

이번편까지 해서 CAN통신은 마무리!

1.녹칸다의 STM32쉴드에 PA0에 붙어있는 가변저항값을 측정해서 CAN통신으로 PC로 전송하기!

/* USER CODE BEGIN 0 */
CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxMessage;
CAN_RxHeaderTypeDef RxMessage;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
//main에서 1회 호출
void Can_Set(){
	sFilterConfig.FilterBank= 0;
	sFilterConfig.FilterMode= CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale= CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterIdHigh= 0x0000;
	sFilterConfig.FilterIdLow= 0x0000;
	sFilterConfig.FilterMaskIdHigh= 0x0000;
	sFilterConfig.FilterMaskIdLow= 0x0000;
	sFilterConfig.FilterFIFOAssignment= CAN_RX_FIFO0;
	sFilterConfig.FilterActivation= ENABLE;
	sFilterConfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
	HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	HAL_CAN_Start(&hcan);
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 Can_Set();
 uint16_t adc_value0 = 0;
 /* USER CODE END 2 */

while (1)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  //CAN데이터로 송신!
		  TxMessage.DLC = 1; //데이터길이
		  TxMessage.ExtId = 0;
		  TxMessage.IDE = CAN_ID_STD;
		  TxMessage.RTR = CAN_RTR_DATA;
		  TxMessage.StdId = 0x600;
		  TxMessage.TransmitGlobalTime = DISABLE;
		  //0~4095범위의 ADC값을 0~255범위로 축소
		  TxData[0] = (uint8_t)(adc_value0/4095.0*255);
		  HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


2.예제1에서 0~4095의 숫자를 각 자리로 나눠서 4byte로 전송하기!

/* USER CODE BEGIN 0 */
CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxMessage;
CAN_RxHeaderTypeDef RxMessage;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
//main에서 1회 호출
void Can_Set(){
	sFilterConfig.FilterBank= 0;
	sFilterConfig.FilterMode= CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale= CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterIdHigh= 0x0000;
	sFilterConfig.FilterIdLow= 0x0000;
	sFilterConfig.FilterMaskIdHigh= 0x0000;
	sFilterConfig.FilterMaskIdLow= 0x0000;
	sFilterConfig.FilterFIFOAssignment= CAN_RX_FIFO0;
	sFilterConfig.FilterActivation= ENABLE;
	sFilterConfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
	HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	HAL_CAN_Start(&hcan);
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
 HAL_ADC_Start(&hadc1); //딱 한번만 호출
 Can_Set();
 uint16_t adc_value0 = 0;
 /* USER CODE END 2 */

while (1)
 {
	  //측정할때마다 호출
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  //CAN데이터로 송신!
		  TxMessage.DLC = 4; //데이터길이
		  TxMessage.ExtId = 0;
		  TxMessage.IDE = CAN_ID_STD;
		  TxMessage.RTR = CAN_RTR_DATA;
		  TxMessage.StdId = 0x600;
		  TxMessage.TransmitGlobalTime = DISABLE;
		  TxData[0] = adc_value0/1000; //천의자리
		  TxData[1] = (adc_value0/100)%10; //백의자리
		  TxData[2] = (adc_value0/10)%10; //십의자리
		  TxData[3] = adc_value0%10; //일의자리
		  HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


3.온습도센서(DHT-11)의 측정값을 CAN통신으로 PC로 전송하기! 

/* USER CODE BEGIN 0 *//* USER CODE BEGIN 2 */
 Can_Set();
 char str[100];
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  uint8_t error_no = DHT_read();
	  if(error_no == 0){  // 정상일 때 처리
		  float temp = 0;
		  float humi = 0;
		  temp = DHT.temp_i;
		  if (DHT.temp_d & 0x80) {
			  temp = -1 - temp;
		  }
		  temp += (DHT.temp_d & 0x0f) * 0.1;
		  humi = DHT.rh_i + DHT.rh_d * 0.1;
		  sprintf(str, "T:%.1f'C H:%.1f%c\n", temp,humi,'%');
		  HAL_UART_Transmit(&huart2,str,strlen(str),100);
		  TxMessage.DLC = 4; //데이터길이
		  TxMessage.ExtId = 0;
		  TxMessage.IDE = CAN_ID_STD;
		  TxMessage.RTR = CAN_RTR_DATA;
		  TxMessage.StdId = 0x600;
		  TxMessage.TransmitGlobalTime = DISABLE;
		  TxData[0] = (uint8_t)temp; //온도의 정수부
		  TxData[1] = ((uint8_t)(temp*10))%10; //온도의 실수부
		  TxData[2] = (uint8_t)humi; //습도의 정부수
		  TxData[3] = ((uint8_t)(humi*10))%10; //습도의 실수부
		  HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
	  }
	  HAL_Delay(2000);
 }


#define delay_ms HAL_Delay
#define SYS_CLOCK    64
#define SYSTICK_LOAD 63999
uint32_t millis_cnt = 0;
uint32_t millis() {
return millis_cnt;
}
uint32_t micros() {
return (millis_cnt & 0x3FFFFF) * 1000 + (SYSTICK_LOAD - SysTick->VAL) / SYS_CLOCK;
}
void delay_us(uint32_t us) {  // 64MHz 보정
if (us > 1) {
  uint32_t count = us * 7 - 6;
  while (count--);
} else {
  uint32_t count = 2;
  while (count--);
}
}

union {
 uint32_t data;
 struct {
   uint8_t temp_d;
   uint8_t temp_i;
   uint8_t rh_d;
   uint8_t rh_i;
 };
} DHT;
uint8_t DHT_read () {
 uint8_t i, check_sum;
 uint32_t start;
 check_sum = 0;
 DHT.data = 0;
 GPIOC->CRL = (GPIOC->CRL&0xFFFFFF0F)|(7<<(1*4));  // Output Open-drain (Master send LOW signal)
 delay_ms(18);
 GPIOC->CRL= (GPIOC->CRL&0xFFFFFF0F)|(4<<(1*4));  // Floating input (Master send HIGH signal & data receive)
 start = micros();
 while (GPIOC->IDR&(1<<1)) {
   if (micros()-start > 50) return 1;  // 20~40us
 }
 start = micros();
 while (!(GPIOC->IDR&(1<<1))) {
   if (micros()-start > 120) return 2;  // 80us
 }
 start = micros();
 while (GPIOC->IDR&(1<<1)) {
   if (micros()-start > 120) return 3;  // 80us
 }
 for (i = 0; i < 32; i++) {
   while (!(GPIOC->IDR&(1<<1))); // 50us
   start = micros();
   while (GPIOC->IDR&(1<<1));
   if (micros()-start > 50) DHT.data |= (0x80000000 >> i); // "0"=26~28us, "1"=70us
 }
 for (i = 0; i < 8; i++) {
   while (!(GPIOC->IDR&(1<<1))); // 50us
   start = micros();
   while (GPIOC->IDR&(1<<1));
   if (micros()-start > 50) check_sum |= (0x80 >> i);
 }
 if ((DHT.rh_i + DHT.rh_d + DHT.temp_i + DHT.temp_d) == check_sum) return 0;
 else return 4;
}

CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxMessage;
CAN_RxHeaderTypeDef RxMessage;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
//main에서 1회 호출
void Can_Set(){
	sFilterConfig.FilterBank= 0;
	sFilterConfig.FilterMode= CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale= CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterIdHigh= 0x0000;
	sFilterConfig.FilterIdLow= 0x0000;
	sFilterConfig.FilterMaskIdHigh= 0x0000;
	sFilterConfig.FilterMaskIdLow= 0x0000;
	sFilterConfig.FilterFIFOAssignment= CAN_RX_FIFO0;
	sFilterConfig.FilterActivation= ENABLE;
	sFilterConfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
	HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	HAL_CAN_Start(&hcan);
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
 Can_Set();
 char str[100];
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  uint8_t error_no = DHT_read();
	  if(error_no == 0){  // 정상일 때 처리
		  float temp = 0;
		  float humi = 0;
		  temp = DHT.temp_i;
		  if (DHT.temp_d & 0x80) {
			  temp = -1 - temp;
		  }
		  temp += (DHT.temp_d & 0x0f) * 0.1;
		  humi = DHT.rh_i + DHT.rh_d * 0.1;
		  sprintf(str, "T:%.1f'C H:%.1f%c\n", temp,humi,'%');
		  HAL_UART_Transmit(&huart2,str,strlen(str),100);
		  TxMessage.DLC = 4; //데이터길이
		  TxMessage.ExtId = 0;
		  TxMessage.IDE = CAN_ID_STD;
		  TxMessage.RTR = CAN_RTR_DATA;
		  TxMessage.StdId = 0x600;
		  TxMessage.TransmitGlobalTime = DISABLE;
		  TxData[0] = (uint8_t)temp; //온도의 정수부
		  TxData[1] = ((uint8_t)(temp*10))%10; //온도의 실수부
		  TxData[2] = (uint8_t)humi; //습도의 정부수
		  TxData[3] = ((uint8_t)(humi*10))%10; //습도의 실수부
		  HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
	  }
	  HAL_Delay(2000);
 }


4.PC프로그램에 0x7DF와 데이터 8byte를 stm32로 전송하면 STM32는 0x7E0이라는 ID와 PC가 보낸 데이터를 그대로 ECHO하도록 하시오!

/* USER CODE BEGIN 0 */
CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxMessage;
CAN_RxHeaderTypeDef RxMessage;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
//main에서 1회 호출
void Can_Set(){
	sFilterConfig.FilterBank= 0;
	sFilterConfig.FilterMode= CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale= CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterIdHigh= 0x0000;
	sFilterConfig.FilterIdLow= 0x0000;
	sFilterConfig.FilterMaskIdHigh= 0x0000;
	sFilterConfig.FilterMaskIdLow= 0x0000;
	sFilterConfig.FilterFIFOAssignment= CAN_RX_FIFO0;
	sFilterConfig.FilterActivation= ENABLE;
	sFilterConfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
	HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	HAL_CAN_Start(&hcan);
}


void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
{
	HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxMessage, RxData);
	if(RxMessage.StdId == 0x7DF){
		TxMessage.DLC = 8; //데이터길이
		TxMessage.ExtId = 0;
		TxMessage.IDE = CAN_ID_STD;
		TxMessage.RTR = CAN_RTR_DATA;
		TxMessage.StdId = 0x7E0;
		TxMessage.TransmitGlobalTime = DISABLE;
		for(int i = 0;i<8;i++){
			TxData[i] = RxData[i];
		}
		HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
	}
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
 Can_Set();
 /* USER CODE END 2 */


5.PC프로그램이 현재 자동차의 속도를 물어보는 PID를 전송하면 STM32는 속도를 255(0xFF)로 고정해서 응답하도록 하시오!

/* USER CODE BEGIN 0 */
CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxMessage;
CAN_RxHeaderTypeDef RxMessage;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
//main에서 1회 호출
void Can_Set(){
	sFilterConfig.FilterBank= 0;
	sFilterConfig.FilterMode= CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale= CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterIdHigh= 0x0000;
	sFilterConfig.FilterIdLow= 0x0000;
	sFilterConfig.FilterMaskIdHigh= 0x0000;
	sFilterConfig.FilterMaskIdLow= 0x0000;
	sFilterConfig.FilterFIFOAssignment= CAN_RX_FIFO0;
	sFilterConfig.FilterActivation= ENABLE;
	sFilterConfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
	HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	HAL_CAN_Start(&hcan);
}


void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
{
	HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxMessage, RxData);
	if(RxMessage.StdId == 0x7DF){
		TxMessage.DLC = 8; //데이터길이
		TxMessage.ExtId = 0;
		TxMessage.IDE = CAN_ID_STD;
		TxMessage.RTR = CAN_RTR_DATA;
		TxMessage.StdId = 0x7E0;
		TxMessage.TransmitGlobalTime = DISABLE;
		uint8_t length = RxData[0];
		uint8_t service_id = RxData[1];
		uint8_t p_id = RxData[2];
		//Vehicle speed
		if(service_id == 0x01 && p_id == 0x0D){
			TxData[0] = 3;
			TxData[1] = service_id;
			TxData[2] = p_id;
			TxData[3] = 255;
			TxData[4] = 0;
			TxData[5] = 0;
			TxData[6] = 0;
			TxData[7] = 0;
			HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
		}
		
	}
}

/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
 Can_Set();
 /* USER CODE END 2 */


6.예제5에서 가변저항을 돌리면 속도가 0~255사이로 변화하도록 하시오!

/* USER CODE BEGIN 0 */
//이 변수가 인터럽트를 포함한 여기저기서 사용할 경우 이 키워드를 붙혀야한다!
volatile uint16_t adc_value0 = 0;
CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxMessage;
CAN_RxHeaderTypeDef RxMessage;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
//main에서 1회 호출
void Can_Set(){
	sFilterConfig.FilterBank= 0;
	sFilterConfig.FilterMode= CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale= CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterIdHigh= 0x0000;
	sFilterConfig.FilterIdLow= 0x0000;
	sFilterConfig.FilterMaskIdHigh= 0x0000;
	sFilterConfig.FilterMaskIdLow= 0x0000;
	sFilterConfig.FilterFIFOAssignment= CAN_RX_FIFO0;
	sFilterConfig.FilterActivation= ENABLE;
	sFilterConfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
	HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	HAL_CAN_Start(&hcan);
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
{
	HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxMessage, RxData);
	if(RxMessage.StdId == 0x7DF){
		TxMessage.DLC = 8; //데이터길이
		TxMessage.ExtId = 0;
		TxMessage.IDE = CAN_ID_STD;
		TxMessage.RTR = CAN_RTR_DATA;
		TxMessage.StdId = 0x7E0;
		TxMessage.TransmitGlobalTime = DISABLE;
		uint8_t length = RxData[0];
		uint8_t service_id = RxData[1];
		uint8_t p_id = RxData[2];
		//Vehicle speed
		if(service_id == 0x01 && p_id == 0x0D){
			TxData[0] = 3;
			TxData[1] = service_id;
			TxData[2] = p_id;
			TxData[3] = (uint8_t)(adc_value0/4095.0*255);
			TxData[4] = 0;
			TxData[5] = 0;
			TxData[6] = 0;
			TxData[7] = 0;
			HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
		}
	}
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
 Can_Set();
 HAL_ADC_Start(&hadc1);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


7.PC프로그램에서 자동차의 엔진RPM을 물어보는 PID를 전송하면 가변저항을 돌려서 엔진 RPM이 최소값에서 최대값 사이로 변화도록 하시오!

/* USER CODE BEGIN 0 */
//이 변수가 인터럽트를 포함한 여기저기서 사용할 경우 이 키워드를 붙혀야한다!
volatile uint16_t adc_value0 = 0;
char tx_buff[50];
CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxMessage;
CAN_RxHeaderTypeDef RxMessage;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
//main에서 1회 호출
void Can_Set(){
	sFilterConfig.FilterBank= 0;
	sFilterConfig.FilterMode= CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale= CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterIdHigh= 0x0000;
	sFilterConfig.FilterIdLow= 0x0000;
	sFilterConfig.FilterMaskIdHigh= 0x0000;
	sFilterConfig.FilterMaskIdLow= 0x0000;
	sFilterConfig.FilterFIFOAssignment= CAN_RX_FIFO0;
	sFilterConfig.FilterActivation= ENABLE;
	sFilterConfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
	HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	HAL_CAN_Start(&hcan);
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
{
	HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxMessage, RxData);
	if(RxMessage.StdId == 0x7DF){
		TxMessage.DLC = 8; //데이터길이
		TxMessage.ExtId = 0;
		TxMessage.IDE = CAN_ID_STD;
		TxMessage.RTR = CAN_RTR_DATA;
		TxMessage.StdId = 0x7E0;
		TxMessage.TransmitGlobalTime = DISABLE;
		uint8_t length = RxData[0];
		uint8_t service_id = RxData[1];
		uint8_t p_id = RxData[2];
		//Engine speed
		if(service_id == 0x01 && p_id == 0x0C){
			TxData[0] = 4;
			TxData[1] = service_id;
			TxData[2] = p_id;
			uint16_t rpm = (uint16_t)(adc_value0/4095.0*16383.75);
			TxData[3] = (rpm*4)/256; //A
			TxData[4] = (rpm*4)%256; //B
			TxData[5] = 0;
			TxData[6] = 0;
			TxData[7] = 0;
			HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
			sprintf(tx_buff,"RPM=%d, A=%02X, B=%02X, C_RPM=%d\n",rpm,TxData[3],TxData[4],(TxData[3]*256+TxData[4])/4);
			HAL_UART_Transmit(&huart2,tx_buff,strlen(tx_buff),100);
		}
	}
}
/* USER CODE END 0 */


/* USER CODE BEGIN 2 */
 Can_Set();
 HAL_ADC_Start(&hadc1);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


8.동일한 방식으로 자동차의 냉각수 온도를 조회하시오!

/* USER CODE BEGIN 0 */
//이 변수가 인터럽트를 포함한 여기저기서 사용할 경우 이 키워드를 붙혀야한다!
volatile uint16_t adc_value0 = 0;
char tx_buff[50];
CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxMessage;
CAN_RxHeaderTypeDef RxMessage;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
//main에서 1회 호출
void Can_Set(){
	sFilterConfig.FilterBank= 0;
	sFilterConfig.FilterMode= CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale= CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterIdHigh= 0x0000;
	sFilterConfig.FilterIdLow= 0x0000;
	sFilterConfig.FilterMaskIdHigh= 0x0000;
	sFilterConfig.FilterMaskIdLow= 0x0000;
	sFilterConfig.FilterFIFOAssignment= CAN_RX_FIFO0;
	sFilterConfig.FilterActivation= ENABLE;
	sFilterConfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
	HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
	HAL_CAN_Start(&hcan);
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
{
	HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxMessage, RxData);
	if(RxMessage.StdId == 0x7DF){
		TxMessage.DLC = 8; //데이터길이
		TxMessage.ExtId = 0;
		TxMessage.IDE = CAN_ID_STD;
		TxMessage.RTR = CAN_RTR_DATA;
		TxMessage.StdId = 0x7E0;
		TxMessage.TransmitGlobalTime = DISABLE;
		uint8_t length = RxData[0];
		uint8_t service_id = RxData[1];
		uint8_t p_id = RxData[2];
		//Engine coolant temperature
		if(service_id == 0x01 && p_id == 0x05){
			TxData[0] = 4;
			TxData[1] = service_id;
			TxData[2] = p_id;
			int16_t temp = (uint16_t)(adc_value0/4095.0*255) -40;
			TxData[3] = temp + 40;
			TxData[4] = 0;
			TxData[5] = 0;
			TxData[6] = 0;
			TxData[7] = 0;
			HAL_CAN_AddTxMessage(&hcan, &TxMessage, TxData, &TxMailbox);
			sprintf(tx_buff,"temp=%d, A=%02X, c_temp=%d\n",temp,TxData[3],TxData[3]-40);
			HAL_UART_Transmit(&huart2,tx_buff,strlen(tx_buff),100);
		}
	}
}

/* USER CODE END 0 */


/* USER CODE BEGIN 2 */
 Can_Set();
 HAL_ADC_Start(&hadc1);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1);
	  }
	  HAL_Delay(100);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }

 

반응형
Posted by 덕력킹
,