stm32: move f103 (bluepill) to common i2c code
Этот коммит содержится в:
родитель
a075cbedf5
коммит
b5205cc3ca
4 изменённых файлов: 47 добавлений и 429 удалений
|
@ -85,6 +85,6 @@ const (
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SDA_PIN = PB7
|
I2C0_SDA_PIN = PB7
|
||||||
SCL_PIN = PB6
|
I2C0_SCL_PIN = PB6
|
||||||
)
|
)
|
||||||
|
|
|
@ -120,6 +120,6 @@ const (
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SCL_PIN = PB6
|
I2C0_SCL_PIN = PB6
|
||||||
SDA_PIN = PB7
|
I2C0_SDA_PIN = PB7
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build stm32,!stm32f103,!stm32f7x2,!stm32l5x2,!stm32l0
|
// +build stm32,!stm32f7x2,!stm32l5x2,!stm32l0
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
|
|
@ -197,10 +197,6 @@ func (spi SPI) configurePins(config SPIConfig) {
|
||||||
|
|
||||||
//---------- I2C related types and code
|
//---------- I2C related types and code
|
||||||
|
|
||||||
type I2C struct {
|
|
||||||
Bus *stm32.I2C_Type
|
|
||||||
}
|
|
||||||
|
|
||||||
// There are 2 I2C interfaces on the STM32F103xx.
|
// There are 2 I2C interfaces on the STM32F103xx.
|
||||||
// Since the first interface is named I2C1, both I2C0 and I2C1 refer to I2C1.
|
// Since the first interface is named I2C1, both I2C0 and I2C1 refer to I2C1.
|
||||||
// TODO: implement I2C2.
|
// TODO: implement I2C2.
|
||||||
|
@ -209,451 +205,73 @@ var (
|
||||||
I2C0 = I2C1
|
I2C0 = I2C1
|
||||||
)
|
)
|
||||||
|
|
||||||
// I2CConfig is used to store config info for I2C.
|
type I2C struct {
|
||||||
type I2CConfig struct {
|
Bus *stm32.I2C_Type
|
||||||
Frequency uint32
|
|
||||||
SCL Pin
|
|
||||||
SDA Pin
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure is intended to setup the I2C interface.
|
func (i2c I2C) configurePins(config I2CConfig) {
|
||||||
func (i2c I2C) Configure(config I2CConfig) error {
|
if config.SDA == PB9 {
|
||||||
// Default I2C bus speed is 100 kHz.
|
|
||||||
if config.Frequency == 0 {
|
|
||||||
config.Frequency = TWI_FREQ_100KHZ
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable clock for I2C
|
|
||||||
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)
|
|
||||||
|
|
||||||
// I2C1 pins
|
|
||||||
switch config.SDA {
|
|
||||||
case PB9:
|
|
||||||
config.SCL = PB8
|
|
||||||
// use alternate I2C1 pins PB8/PB9 via AFIO mapping
|
// use alternate I2C1 pins PB8/PB9 via AFIO mapping
|
||||||
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
|
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)
|
||||||
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_I2C1_REMAP)
|
stm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_I2C1_REMAP)
|
||||||
default:
|
|
||||||
// use default I2C1 pins PB6/PB7
|
|
||||||
config.SDA = SDA_PIN
|
|
||||||
config.SCL = SCL_PIN
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config.SDA.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})
|
config.SDA.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})
|
||||||
config.SCL.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})
|
config.SCL.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})
|
||||||
|
}
|
||||||
|
|
||||||
// Disable the selected I2C peripheral to configure
|
func (i2c I2C) getFreqRange(config I2CConfig) uint32 {
|
||||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)
|
|
||||||
|
|
||||||
// pclk1 clock speed is main frequency divided by PCLK1 prescaler (div 2)
|
// pclk1 clock speed is main frequency divided by PCLK1 prescaler (div 2)
|
||||||
pclk1 := CPUFrequency() / 2
|
pclk1 := CPUFrequency() / 2
|
||||||
|
|
||||||
// set freqency range to PCLK1 clock speed in MHz
|
// set freqency range to PCLK1 clock speed in MHz
|
||||||
// aka setting the value 36 means to use 36 MHz clock
|
// aka setting the value 36 means to use 36 MHz clock
|
||||||
pclk1Mhz := pclk1 / 1000000
|
return pclk1 / 1000000
|
||||||
i2c.Bus.CR2.SetBits(pclk1Mhz)
|
|
||||||
|
|
||||||
switch config.Frequency {
|
|
||||||
case TWI_FREQ_100KHZ:
|
|
||||||
// Normal mode speed calculation
|
|
||||||
ccr := pclk1 / (config.Frequency * 2)
|
|
||||||
i2c.Bus.CCR.Set(ccr)
|
|
||||||
|
|
||||||
// duty cycle 2
|
|
||||||
i2c.Bus.CCR.ClearBits(stm32.I2C_CCR_DUTY)
|
|
||||||
|
|
||||||
// frequency standard mode
|
|
||||||
i2c.Bus.CCR.ClearBits(stm32.I2C_CCR_F_S)
|
|
||||||
|
|
||||||
// Set Maximum Rise Time for standard mode
|
|
||||||
i2c.Bus.TRISE.Set(pclk1Mhz)
|
|
||||||
|
|
||||||
case TWI_FREQ_400KHZ:
|
|
||||||
// Fast mode speed calculation
|
|
||||||
ccr := pclk1 / (config.Frequency * 3)
|
|
||||||
i2c.Bus.CCR.Set(ccr)
|
|
||||||
|
|
||||||
// duty cycle 2
|
|
||||||
i2c.Bus.CCR.ClearBits(stm32.I2C_CCR_DUTY)
|
|
||||||
|
|
||||||
// frequency fast mode
|
|
||||||
i2c.Bus.CCR.SetBits(stm32.I2C_CCR_F_S)
|
|
||||||
|
|
||||||
// Set Maximum Rise Time for fast mode
|
|
||||||
i2c.Bus.TRISE.Set(((pclk1Mhz * 300) / 1000))
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-enable the selected I2C peripheral
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tx does a single I2C transaction at the specified address.
|
func (i2c I2C) getRiseTime(config I2CConfig) uint32 {
|
||||||
// It clocks out the given address, writes the bytes in w, reads back len(r)
|
// These bits must be programmed with the maximum SCL rise time given in the
|
||||||
// bytes and stores them in r, and generates a stop condition on the bus.
|
// I2C bus specification, incremented by 1.
|
||||||
func (i2c I2C) Tx(addr uint16, w, r []byte) error {
|
// For instance: in Sm mode, the maximum allowed SCL rise time is 1000 ns.
|
||||||
var err error
|
// If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to 0x08
|
||||||
if len(w) != 0 {
|
// and PCLK1 = 125 ns, therefore the TRISE[5:0] bits must be programmed with
|
||||||
// start transmission for writing
|
// 09h (1000 ns / 125 ns = 8 + 1)
|
||||||
err = i2c.signalStart()
|
freqRange := i2c.getFreqRange(config)
|
||||||
if err != nil {
|
if config.Frequency > 100000 {
|
||||||
return err
|
// fast mode (Fm) adjustment
|
||||||
|
freqRange *= 300
|
||||||
|
freqRange /= 1000
|
||||||
}
|
}
|
||||||
|
return (freqRange + 1) << stm32.I2C_TRISE_TRISE_Pos
|
||||||
// send address
|
|
||||||
err = i2c.sendAddress(uint8(addr), true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, b := range w {
|
|
||||||
err = i2c.WriteByte(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sending stop here for write
|
|
||||||
err = i2c.signalStop()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(r) != 0 {
|
|
||||||
// re-start transmission for reading
|
|
||||||
err = i2c.signalStart()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 byte
|
|
||||||
switch len(r) {
|
|
||||||
case 1:
|
|
||||||
// send address
|
|
||||||
err = i2c.sendAddress(uint8(addr), false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable ACK of received data
|
|
||||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
|
|
||||||
|
|
||||||
// clear timeout here
|
|
||||||
timeout := i2cTimeout
|
|
||||||
for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CWriteTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate stop condition
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
|
||||||
|
|
||||||
timeout = i2cTimeout
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_RxNE) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CReadTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read and return data byte from I2C data register
|
|
||||||
r[0] = byte(i2c.Bus.DR.Get())
|
|
||||||
|
|
||||||
// wait for stop
|
|
||||||
return i2c.waitForStop()
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
// enable pos
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_POS)
|
|
||||||
|
|
||||||
// Enable ACK of received data
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
|
|
||||||
|
|
||||||
// send address
|
|
||||||
err = i2c.sendAddress(uint8(addr), false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear address here
|
|
||||||
timeout := i2cTimeout
|
|
||||||
for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CWriteTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable ACK of received data
|
|
||||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
|
|
||||||
|
|
||||||
// wait for btf. we need a longer timeout here than normal.
|
|
||||||
timeout = 1000
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CReadTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate stop condition
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
|
||||||
|
|
||||||
// read the 2 bytes by reading twice.
|
|
||||||
r[0] = byte(i2c.Bus.DR.Get())
|
|
||||||
r[1] = byte(i2c.Bus.DR.Get())
|
|
||||||
|
|
||||||
// wait for stop
|
|
||||||
err = i2c.waitForStop()
|
|
||||||
|
|
||||||
//disable pos
|
|
||||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
|
|
||||||
|
|
||||||
return err
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
// Enable ACK of received data
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
|
|
||||||
|
|
||||||
// send address
|
|
||||||
err = i2c.sendAddress(uint8(addr), false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear address here
|
|
||||||
timeout := i2cTimeout
|
|
||||||
for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CWriteTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable ACK of received data
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
|
|
||||||
|
|
||||||
// wait for btf. we need a longer timeout here than normal.
|
|
||||||
timeout = 1000
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CReadTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable ACK of received data
|
|
||||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
|
|
||||||
|
|
||||||
// read the first byte
|
|
||||||
r[0] = byte(i2c.Bus.DR.Get())
|
|
||||||
|
|
||||||
timeout = 1000
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CReadTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate stop condition
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
|
||||||
|
|
||||||
// read the last 2 bytes by reading twice.
|
|
||||||
r[1] = byte(i2c.Bus.DR.Get())
|
|
||||||
r[2] = byte(i2c.Bus.DR.Get())
|
|
||||||
|
|
||||||
// wait for stop
|
|
||||||
return i2c.waitForStop()
|
|
||||||
|
|
||||||
default:
|
|
||||||
// more than 3 bytes of data to read
|
|
||||||
|
|
||||||
// send address
|
|
||||||
err = i2c.sendAddress(uint8(addr), false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear address here
|
|
||||||
timeout := i2cTimeout
|
|
||||||
for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CWriteTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(r)-3; i++ {
|
|
||||||
// Enable ACK of received data
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)
|
|
||||||
|
|
||||||
// wait for btf. we need a longer timeout here than normal.
|
|
||||||
timeout = 1000
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CReadTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the next byte
|
|
||||||
r[i] = byte(i2c.Bus.DR.Get())
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for btf. we need a longer timeout here than normal.
|
|
||||||
timeout = 1000
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_BTF) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CReadTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable ACK of received data
|
|
||||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)
|
|
||||||
|
|
||||||
// get third from last byte
|
|
||||||
r[len(r)-3] = byte(i2c.Bus.DR.Get())
|
|
||||||
|
|
||||||
// Generate stop condition
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
|
||||||
|
|
||||||
// get second from last byte
|
|
||||||
r[len(r)-2] = byte(i2c.Bus.DR.Get())
|
|
||||||
|
|
||||||
timeout = i2cTimeout
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_RxNE) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CReadTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get last byte
|
|
||||||
r[len(r)-1] = byte(i2c.Bus.DR.Get())
|
|
||||||
|
|
||||||
// wait for stop
|
|
||||||
return i2c.waitForStop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const i2cTimeout = 1000
|
func (i2c I2C) getSpeed(config I2CConfig) uint32 {
|
||||||
|
ccr := func(pclk uint32, freq uint32, coeff uint32) uint32 {
|
||||||
// signalStart sends a start signal.
|
return (((pclk - 1) / (freq * coeff)) + 1) & stm32.I2C_CCR_CCR_Msk
|
||||||
func (i2c I2C) signalStart() error {
|
|
||||||
// Wait until I2C is not busy
|
|
||||||
timeout := i2cTimeout
|
|
||||||
for i2c.Bus.SR2.HasBits(stm32.I2C_SR2_BUSY) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CSignalStartTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear stop
|
|
||||||
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_STOP)
|
|
||||||
|
|
||||||
// Generate start condition
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)
|
|
||||||
|
|
||||||
// Wait for I2C EV5 aka SB flag.
|
|
||||||
timeout = i2cTimeout
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_SB) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CSignalStartTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// signalStop sends a stop signal and waits for it to succeed.
|
|
||||||
func (i2c I2C) signalStop() error {
|
|
||||||
// Generate stop condition
|
|
||||||
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)
|
|
||||||
|
|
||||||
// wait for stop
|
|
||||||
return i2c.waitForStop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// waitForStop waits after a stop signal.
|
|
||||||
func (i2c I2C) waitForStop() error {
|
|
||||||
// Wait until I2C is stopped
|
|
||||||
timeout := i2cTimeout
|
|
||||||
for i2c.Bus.SR1.HasBits(stm32.I2C_SR1_STOPF) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CSignalStopTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send address of device we want to talk to
|
|
||||||
func (i2c I2C) sendAddress(address uint8, write bool) error {
|
|
||||||
data := (address << 1)
|
|
||||||
if !write {
|
|
||||||
data |= 1 // set read flag
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c.Bus.DR.Set(uint32(data))
|
|
||||||
|
|
||||||
// Wait for I2C EV6 event.
|
|
||||||
// Destination device acknowledges address
|
|
||||||
timeout := i2cTimeout
|
|
||||||
if write {
|
|
||||||
// EV6 which is ADDR flag.
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_ADDR) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CWriteTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout = i2cTimeout
|
|
||||||
for !i2c.Bus.SR2.HasBits(stm32.I2C_SR2_MSL | stm32.I2C_SR2_BUSY | stm32.I2C_SR2_TRA) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CWriteTimeout
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
sm := func(pclk uint32, freq uint32) uint32 { // standard mode (Sm)
|
||||||
|
if s := ccr(pclk, freq, 2); s < 4 {
|
||||||
|
return 4
|
||||||
} else {
|
} else {
|
||||||
// I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED which is ADDR flag.
|
return s
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_ADDR) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CWriteTimeout
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fm := func(pclk uint32, freq uint32, duty uint8) uint32 { // fast mode (Fm)
|
||||||
|
if duty == DutyCycle2 {
|
||||||
|
return ccr(pclk, freq, 3)
|
||||||
|
} else {
|
||||||
|
return ccr(pclk, freq, 25) | stm32.I2C_CCR_DUTY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clock := CPUFrequency() / 2
|
||||||
|
if config.Frequency <= 100000 {
|
||||||
|
return sm(clock, config.Frequency)
|
||||||
|
} else {
|
||||||
|
s := fm(clock, config.Frequency, config.DutyCycle)
|
||||||
|
if (s & stm32.I2C_CCR_CCR_Msk) == 0 {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return s | stm32.I2C_CCR_F_S
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteByte writes a single byte to the I2C bus.
|
|
||||||
func (i2c I2C) WriteByte(data byte) error {
|
|
||||||
// Send data byte
|
|
||||||
i2c.Bus.DR.Set(uint32(data))
|
|
||||||
|
|
||||||
// Wait for I2C EV8_2 when data has been physically shifted out and
|
|
||||||
// output on the bus.
|
|
||||||
// I2C_EVENT_MASTER_BYTE_TRANSMITTED is TXE flag.
|
|
||||||
timeout := i2cTimeout
|
|
||||||
for !i2c.Bus.SR1.HasBits(stm32.I2C_SR1_TxE) {
|
|
||||||
timeout--
|
|
||||||
if timeout == 0 {
|
|
||||||
return errI2CWriteTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче