问题描述
几天来,我一直在研究I2C操作,以使用PCA9534PW控制多个STM32F334K8T6 I / O扩展器。
我研究了文档并提出了一些代码(由于我对理解寄存器感兴趣,所以我不使用HAL)。
#include "main.h"
#include "stdio.h"
// Functions
/*** Clock and timers sections ***/
// System clock settings
int systemClockInit() {
// Start clock sequence
/*
1 - RUN HSE + WAIT ready
2 - Configure PLL
3 - EN PLL + WAIT ready
4 - Set flash wait cycles
5 - Set bus divider
6 - Switch to PLL mode
7 - disable HSI (Optional)
*/
// Body
int waitCounter = 0;
// & - bit "AND" -> 1 & 1 = 1 or = 0 (Compare bits)
// Run HSE clock (HSEON - 16bit)
// 1 << 16 -> turn on 1 on 16 bit
RCC->CR |= (1 << 16);
// HSEREADY wait
for(waitCounter = 0; ; waitCounter++) {
if(RCC->CR & (1 << 17)) { break; } // If HSE success enabled
if(waitCounter > 0x1000) {
// Clear HSEON bit
// (Replace 1 - 0 / 0 - 1,bit and - clear 16 bit,save other)
RCC->CR &= ~(1 << 16);
return 1;
}
}
// Configure PLL
// 24mHz (x3)
RCC->CFGR |= (0x1 << 18) // PLL x3 (0x1 = 0001),18 - start PLLMULL sector
| (0x01 << 16); // Enable PLL src on HSE clock
// Enable PLL
RCC->CR |= (1 << 24); // 24 bit - PLLON
// PLL enable WAIT
for(waitCounter = 0; ; waitCounter++) {
if(RCC->CR & (1 << 25)) { break; } // If PLL success enabled
if(waitCounter > 0x1000) {
RCC->CR &= ~(1 << 16); // disable HSE
RCC->CR &= ~(1 << 24); // disable PLL
return 2;
}
}
// Set flash wait counter and bus divider
// Core frequency = 24mHz -> set zero wait cycles
FLASH->ACR |= (0x00 << 0); // 0x00 = 000,0 latency position sector
// Set bus dividers
RCC->CFGR |= (0x00 << 11) // PPRE2 divider disabled (000)
// For < 36mHz
| (0x00 << 8) // APB1 divider disabled (000)
// Wait reconnect to PLL
RCC->CFGR |= (0x02 << 0);
while((RCC->CFGR & 0x08) != (0x02 << 2)) {} // 0x08 - RCC_CFGR_SWS_MSK (00001100). 0x02 - 00000010 - PLL selected sysclk,2 - SWS bits position
// disabled HSI clock
RCC->CR &= ~(1 << 0); // disabled HSI
// Return 0 (Success)
return 0;
}
void I2C_Init(void);
void I2C_Start(void);
void I2C_WriteData(void);
// Main function
int main(void)
{
// System Clock init
systemClockInit();
//printf("State: %d",state);
RCC->AHBENR |= (1 << 17) | (1 << 18); // PORTA and PORTB clock enabled
// Configure ms timer
#define coreFrequency 24000000 // 72mHz core frequency
SysTick_Config(coreFrequency / 1000);
I2C_Init();
I2C_Start();
// Loop
while (1)
{
I2C_WriteData();
}
}
void I2C_Init(void) {
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // PORT B clock EN
// I2C pins settings
GPIOB->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7; // Open-Drain PB6,PB7
GPIOB->AFR[0] |= (0x04 << 16); // AF4 (PORTB)
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR6; // AF (PB6)
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR7; // AF (PB7)
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // EN i2c clock
// I2C bus settings
//RCC->APB1RSTR |= (1 << 21); // I2C reset
I2C1->CR1 |= (0 << 0); // I2C peripheral disabled
I2C1->CR1 |= (1 << 12); // I2C analog filter disabled
I2C1->TIMINGR |= 0x00506682; // I2C timing (0x2000090E)
I2C1->CR1 |= (1 << 17); // Clock stretching disabled
I2C1->CR1 |= (1 << 1); // Enable TXIS interrupt
I2C1->CR1 |= (1 << 0); // I2C peripheral enabled
}
void I2C_Start(void) {
while(I2C1->ISR & 15); // wait untin bus not busy
I2C1->CR2 |= (0x4 << 16); // 4 bytes (NBYTE)
I2C1->CR2 |= (1 << 25); // AUTOEND EN
I2C1->CR2 |= (0x20 << 0); // Slave address
I2C1->CR2 |= (1 << 13); // Set START
}
void I2C_WriteData(void) {
static int byteCounter = 0;
if((I2C1->ISR & 1) && !byteCounter) {
I2C1->TXDR = 0x03; // send byte #1
byteCounter++;
return;
}
else if((I2C1->ISR & 1) && byteCounter == 1) {
I2C1->TXDR = 0x0; // send byte #2
byteCounter++;
return;
}
else if((I2C1->ISR & 1) && byteCounter == 3) {
I2C1->TXDR = 0x01; // send byte #3
byteCounter++;
return;
}
else if((I2C1->ISR & 1) && byteCounter == 4) {
I2C1->TXDR = 0xf8; // send byte #4
byteCounter++;
return;
}
}
总线频率APB1 = 24MHz(必须运行计时器)。
I2C频率100kHz,主模式。
我只想向地址为0x20的设备发送4个字节。
我也看了 F0系列的官方代码片段,那里有一个类似的I2C示例,但是没有从主机发送的详细过程。
您能帮我找到错误吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)