기록 차원에서 남겨둡니다.

 

STM32F103xC 를 사용했는데 PWM 시그널이 2가지가 필요했습니다.

그런데 TIM3 CH4에서 TIM8 데이터가 나옵니다.

칩 불량인가? 다른 칩에서도 같은 문제가 나오네요.

이 문제로 많은 시간을 허비하며 문제점 파악에 나섰고,

TIM 내부 블럭도와 CubeIDE 에서 실마리를 발견했습니다.

 

문제가 발생한 PWM Pin 을 살펴보는중 Remap 사용시 TIM8 CH3N 을 발견했습니다. 

 

 

 

이 N은 뭐하는 걸까?

PWM 신호를 RS485와 같이 미러신호가 필요할 경우가 있을껍니다. 아니면 똑같은 시그널을요.

어쨌든 PWM 시그널을 다른 포트로 내보낼 수 있습니다. 즉 GPIOC 를 사용하는 TIM8 에서 GPIOB 로 TIM6를 ㅁ

아무튼 코드에서 붉은색 부분이 문제였습니다.

 

  TIM_OCInitTypeDef  TIM_OCInitStructure;
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
  TIM_OCInitStructure.TIM_Pulse = 0;
  TIM_OC3Init(TIM8, &TIM_OCInitStructure);

 

정리하면 타이머 블록을 보면 신호가 분기되어 2곳으로 내보낼수 있습니다.

출력 여부를 결정하는 TIM_OutputState, TIM_OutputNState 의 값을 반드시 지정해야 합니다.

특히 구조체변수 TIM_OCInitStructure 선언시 기본 값이 셋팅되는 것이 아니므로 꼭! 설정값 여부를 지정해야 합니다.

 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;

이렇게 해주면 TIM3의 CH4 와 TIM8의 CH3N 의 충돌이 해결됩니다.

 

굿밤~!

Posted by +깡통+

오늘 또 식겁? 했다.

분명이 두달전에 파생된 펌웨어는 통신이 잘 되는데!!!

원본 펌웨어는 쓰레기 값이 자꾸만 수신된다.

PC에서 송신하면 STM32에서 계속 다른 응답이 전방에 섞여서 왔다.

 

왜! 왜!

 

결국 파생된 소스와 원본을 면밀히 검토한 결과 상수 RESET 의 문제였다.

종종 아래의 코드처럼 KEY 값을 정의한다.  

9번 값이 보이시는가?

특정 조합을 누르면 SoftReset을 하려고 만든게 화근!

 

#define UP      1
#define DOWN    2
#define LEFT    3
#define RIGHT   4
#define ENTER   5
#define CANCEL  6
#define RESET   9

#define ON 1
#define OFF 0

 

9번으로 인하 아래 코드에 영향을 받았다.

따라서 수신 인터럽트를 처리하러 왔다가.

송신까지 건들게 되는게 원인이었다.


void USART2_IRQHandler(void)  // RS232
{
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
  {
    /* Read one byte from the receive data register */
    USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    RxBuffer2[RxHead2++] = USART_ReceiveData(USART2);   
    if(RxHead2 == MAX_RX2_BUFFER_SIZE) RxHead2 = 0;
  }
  
  if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)
  {  
    /* Write one byte to the transmit data register */
    USART_SendData(USART2, TxBuffer2[TxTail2++]);
   
    if(TxTail2 == MAX_TX2_BUFFER_SIZE) TxTail2 = 0;
   
    if(TxTail2 == TxHead2)
    {
      /* Disable the USARTz Transmit interrupt */
      USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
    }
  }
}

 

 

다음에는 같은 실수 반복하지 말자!

Posted by +깡통+

보통은 I2C EEPROM을 많이 이용하는데 어쩌다보니 SPI로 설계해 버렸다.

그로 인해서 시간을 조금 허비? 했다.


SPI Write를 하는데 1 PAGE만 쓰기가 가능하고 이후 데이터를 오리무중이다..

정말 쓰기가 잘못 된건지 반대로 읽기가 안되는건지 종일 고민했다.


AT25040B 의 경우 아이러니 하게도 WREN 명령을 1 PAGE Write 할때마다 줘야한다. 이게 포인트...



void SPI_Flash_WriteArray(uint16_t address, uint8_t *data, uint8_t len) { uint16_t addr = address; uint8_t i = 0; while( i < len ) { SPI_Flash_WriteEnable();    // <== 이놈이 문제였음. EEPROM_CS_LOW(); SPI_SendByte(WRITE); // 명령선택 //SPI_SendByte((addr & 0xFF00) >> 8); // 상위어드레스를 쓸 경우 SPI_SendByte(addr & 0xFF); // 하위어드레스 for(; i < len;) { SPI_SendByte(data[i++]); // 쓸 데이터 1 Byte씩 보내기 if(++addr % PAGE_SIZE == 0) { break; } } EEPROM_CS_HIGH(); delay_ms(10);    // 칩마다 틀리지만 쓰기를 실행하는데 5ms 필요하다. } }


Posted by +깡통+

최신 Wiznet 사의 W5500 칩을 테스트 하던중에 발견.

최신드라이버 파일이라고 잘 정리해 둔것을 보고 써보던중에 발견함.

 


uint8_t  getIMR(void)
{
   return WIZCHIP_READ(IMRw);  // 이렇게 수정함.
}

 


uint8_t  getIMR(void)
{
   return WIZCHIP_READ(IMRw);
}

 

#define IMRw               (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3))

 

RCR 도 마찬가지~

 

 

D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2861 #define  EXTI_IMR_MR10                       ((uint32_t)0x00000400)        /*!< Interrupt Mask on line 10 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2862 #define  EXTI_IMR_MR11                       ((uint32_t)0x00000800)        /*!< Interrupt Mask on line 11 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2863 #define  EXTI_IMR_MR12                       ((uint32_t)0x00001000)        /*!< Interrupt Mask on line 12 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2864 #define  EXTI_IMR_MR13                       ((uint32_t)0x00002000)        /*!< Interrupt Mask on line 13 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2865 #define  EXTI_IMR_MR14                       ((uint32_t)0x00004000)        /*!< Interrupt Mask on line 14 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2866 #define  EXTI_IMR_MR15                       ((uint32_t)0x00008000)        /*!< Interrupt Mask on line 15 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2867 #define  EXTI_IMR_MR16                       ((uint32_t)0x00010000)        /*!< Interrupt Mask on line 16 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2868 #define  EXTI_IMR_MR17                       ((uint32_t)0x00020000)        /*!< Interrupt Mask on line 17 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2869 #define  EXTI_IMR_MR18                       ((uint32_t)0x00040000)        /*!< Interrupt Mask on line 18 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 2870 #define  EXTI_IMR_MR19                       ((uint32_t)0x00080000)        /*!< Interrupt Mask on line 19 */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 7511 #define ETH_MACIMR_TSTIM     ((uint32_t)0x00000200)  /* Time stamp trigger interrupt mask */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 7512 #define ETH_MACIMR_PMTIM     ((uint32_t)0x00000008)  /* PMT interrupt mask */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 7586 #define ETH_MMCRIMR_RGUFM    ((uint32_t)0x00020000)  /* Mask the interrupt when Rx good unicast frames counter reaches half the maximum value */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 7587 #define ETH_MMCRIMR_RFAEM    ((uint32_t)0x00000040)  /* Mask the interrupt when when Rx alignment error counter reaches half the maximum value */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 7588 #define ETH_MMCRIMR_RFCEM    ((uint32_t)0x00000020)  /* Mask the interrupt when Rx crc error counter reaches half the maximum value */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 7591 #define ETH_MMCTIMR_TGFM     ((uint32_t)0x00200000)  /* Mask the interrupt when Tx good frame count counter reaches half the maximum value */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 7592 #define ETH_MMCTIMR_TGFMSCM  ((uint32_t)0x00008000)  /* Mask the interrupt when Tx good multi col counter reaches half the maximum value */
D:\test\Libraries\CMSIS\Core\CM3\stm32f10x.h 7593 #define ETH_MMCTIMR_TGFSCM   ((uint32_t)0x00004000)  /* Mask the interrupt when Tx good single col counter reaches half the maximum value */
D:\test\Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_exti.c 86 EXTI->IMR = 0x00000000;
D:\test\Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_exti.c 115 EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line;
D:\test\Libraries\STM32F10x_StdPeriph_Driver\src\stm32f10x_exti.c 230 enablestatus =  EXTI->IMR & EXTI_Line;
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\netctrl.c 82 setIMR((uint8_t)(option_value&0x00FF)); // set interrupt mask.
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 373 void     setIMR(uint8_t imr)
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 373 void     setIMR(uint8_t imr)
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 375 WIZCHIP_WRITE(IMR, imr);
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 375 WIZCHIP_WRITE(IMR, imr);
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 378 uint8_t  getIMR(void)
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 380 return WIZCHIP_READ(IMR);
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 393 void     setSIMR(uint8_t simr)
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 393 void     setSIMR(uint8_t simr)
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 395 WIZCHIP_WRITE(SIMR, simr);
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 395 WIZCHIP_WRITE(SIMR, simr);
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 398 uint8_t  getSIMR(void)
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 400 return WIZCHIP_READ(SIMR);
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 547 void     setSn_IMR(uint8_t sn, uint8_t imr)
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 547 void     setSn_IMR(uint8_t sn, uint8_t imr)
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 549 WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0xF0));
D:\test\Libraries\W5500_iolibrary_v100\ethernet\w5500\w5500.c 549 WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0xF0));

Posted by +깡통+
이전버튼 1 이전버튼