| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632 |
- /**
- **************************************************************************
- * @file at32f415_i2c.c
- * @version v2.0.5
- * @date 2022-05-20
- * @brief contains all the functions for the i2c firmware library
- **************************************************************************
- * Copyright notice & Disclaimer
- *
- * The software Board Support Package (BSP) that is made available to
- * download from Artery official website is the copyrighted work of Artery.
- * Artery authorizes customers to use, copy, and distribute the BSP
- * software and its related documentation for the purpose of design and
- * development in conjunction with Artery microcontrollers. Use of the
- * software is governed by this copyright notice and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
- * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
- * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
- * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
- * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
- *
- **************************************************************************
- */
- #include "at32f415_conf.h"
- /** @addtogroup AT32F415_periph_driver
- * @{
- */
- /** @defgroup I2C
- * @brief I2C driver modules
- * @{
- */
- #ifdef I2C_MODULE_ENABLED
- /** @defgroup I2C_private_functions
- * @{
- */
- /**
- * @brief reset the i2c register
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @retval none
- */
- void i2c_reset(i2c_type *i2c_x)
- {
- if(i2c_x == I2C1)
- {
- crm_periph_reset(CRM_I2C1_PERIPH_RESET, TRUE);
- crm_periph_reset(CRM_I2C1_PERIPH_RESET, FALSE);
- }
- else if(i2c_x == I2C2)
- {
- crm_periph_reset(CRM_I2C2_PERIPH_RESET, TRUE);
- crm_periph_reset(CRM_I2C2_PERIPH_RESET, FALSE);
- }
- }
- /**
- * @brief software reset.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_software_reset(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.reset = new_state;
- }
- /**
- * @brief init i2c speed and duty cycle.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param duty
- * this parameter can be one of the following values:
- * - I2C_FSMODE_DUTY_2_1: duty cycle 2:1
- * - I2C_FSMODE_DUTY_16_9: duty cycle 16:9
- * @param speed: i2c scl clock speed, such as 100000
- * @retval none
- */
- void i2c_init(i2c_type *i2c_x, i2c_fsmode_duty_cycle_type duty, uint32_t speed)
- {
- uint32_t apb_freq = 0;
- uint16_t freq_mhz = 0, temp = 0;
- crm_clocks_freq_type clocks;
- /* disable i2c peripherals */
- i2c_x->ctrl1_bit.i2cen = FALSE;
- /* get system clock */
- crm_clocks_freq_get(&clocks);
- if((i2c_x == I2C1) || (i2c_x == I2C2))
- {
- apb_freq = clocks.apb1_freq;
- }
- freq_mhz = (apb_freq / 1000000);
- /* set i2c input clock frequency */
- i2c_x->ctrl2_bit.clkfreq = freq_mhz;
- /* standard mode */
- if(speed <= 100000)
- {
- temp = (uint16_t)(apb_freq / (speed << 1));
- if (temp < 0x04)
- {
- temp = 0x04;
- }
- /* set scl clock */
- i2c_x->clkctrl_bit.speed = temp;
- /* disable fast mode */
- i2c_x->clkctrl_bit.speedmode = FALSE;
- /* set the maximum rise time */
- if((freq_mhz + 1) > 0x3F)
- {
- i2c_x->tmrise_bit.risetime = 0x3F;
- }
- else
- {
- i2c_x->tmrise_bit.risetime = (freq_mhz + 1);
- }
- }
- /* fast mode */
- else
- {
- if (duty == I2C_FSMODE_DUTY_2_1)
- {
- temp = (uint16_t)(apb_freq / (speed * 3));
- /* the ratio of high level to low level is 1:2 */
- i2c_x->clkctrl_bit.dutymode = I2C_FSMODE_DUTY_2_1;
- }
- else
- {
- temp = (uint16_t)(apb_freq / (speed * 25));
- /* the ratio of high level to low level is 9:16 */
- i2c_x->clkctrl_bit.dutymode = I2C_FSMODE_DUTY_16_9;
- }
- if (temp == 0)
- {
- temp = 0x0001;
- }
- /* set scl clock*/
- i2c_x->clkctrl_bit.speed = temp;
- /* set the mode to fast mode */
- i2c_x->clkctrl_bit.speedmode = TRUE;
- /* set the maximum rise time */
- i2c_x->tmrise_bit.risetime = (uint16_t)(((freq_mhz * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1);
- }
- }
- /**
- * @brief config own address1.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param mode
- * this parameter can be one of the following values:
- * - I2C_ADDRESS_MODE_7BIT: 7bit address.
- * - I2C_ADDRESS_MODE_10BIT: 10bit address.
- * @param address: own address1, such as 0xb0.
- * @retval none
- */
- void i2c_own_address1_set(i2c_type *i2c_x, i2c_address_mode_type mode, uint16_t address)
- {
- /* set address mode */
- i2c_x->oaddr1_bit.addr1mode = mode;
- /* set own address1 */
- i2c_x->oaddr1_bit.addr1 = address;
- }
- /**
- * @brief config own address2.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param address: specifies the 7bit i2c own address2, such as 0xa0.
- * @retval none.
- */
- void i2c_own_address2_set(i2c_type *i2c_x, uint8_t address)
- {
- i2c_x->oaddr2_bit.addr2 = (address >> 1);
- }
- /**
- * @brief enable or disable own address2.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_own_address2_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->oaddr2_bit.addr2en = new_state;
- }
- /**
- * @brief enable or disable the smbus mode
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_smbus_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.permode = new_state;
- }
- /**
- * @brief enable or disable i2c periph
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.i2cen = new_state;
- }
- /**
- * @brief config fast mode duty cycle
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param duty
- * this parameter can be one of the following values:
- * - I2C_FSMODE_DUTY_2_1: duty cycle 2:1
- * - I2C_FSMODE_DUTY_16_9: duty cycle 16:9
- * @retval none
- */
- void i2c_fast_mode_duty_set(i2c_type *i2c_x, i2c_fsmode_duty_cycle_type duty)
- {
- i2c_x->clkctrl_bit.dutymode = duty;
- }
- /**
- * @brief enable or disable clock stretch.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_clock_stretch_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.stretch = !new_state;
- }
- /**
- * @brief enable or disable acknowledge.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none.
- */
- void i2c_ack_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.acken = new_state;
- }
- /**
- * @brief master receiving mode acknowledge control.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param pos
- * this parameter can be one of the following values:
- * - I2C_MASTER_ACK_CURRENT: acken bit acts on the current byte
- * - I2C_MASTER_ACK_NEXT: acken bit acts on the next byte
- * @retval none
- */
- void i2c_master_receive_ack_set(i2c_type *i2c_x, i2c_master_ack_type pos)
- {
- i2c_x->ctrl1_bit.mackctrl = pos;
- }
- /**
- * @brief pec position set.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param pos
- * this parameter can be one of the following values:
- * - I2C_PEC_POSITION_CURRENT: the current byte is pec
- * - I2C_PEC_POSITION_NEXT: the next byte is pec
- * @retval none
- */
- void i2c_pec_position_set(i2c_type *i2c_x, i2c_pec_position_type pos)
- {
- i2c_x->ctrl1_bit.mackctrl = pos;
- }
- /**
- * @brief enable or disable general call.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_general_call_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.gcaen = new_state;
- }
- /**
- * @brief enable or disable arp mode.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_arp_mode_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.arpen = new_state;
- }
- /**
- * @brief config smbus host or device.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param level
- * this parameter can be one of the following values:
- * - I2C_SMBUS_MODE_DEVICE: smbus device.
- * - I2C_SMBUS_MODE_HOST: smbus host.
- * @retval none
- */
- void i2c_smbus_mode_set(i2c_type *i2c_x, i2c_smbus_mode_set_type mode)
- {
- i2c_x->ctrl1_bit.smbmode = mode;
- }
- /**
- * @brief drive the smbus alert pin high or low.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param level
- * this parameter can be one of the following values:
- * - I2C_SMBUS_ALERT_LOW: smbus alert pin set low.
- * - I2C_SMBUS_ALERT_HIGH: smbus alert pin set high.
- * @retval none
- */
- void i2c_smbus_alert_set(i2c_type *i2c_x, i2c_smbus_alert_set_type level)
- {
- i2c_x->ctrl1_bit.smbalert = level;
- }
- /**
- * @brief enable or disable pec transfer.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_pec_transmit_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.pecten = new_state;
- }
- /**
- * @brief enable or disable pec calcultetion.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_pec_calculate_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl1_bit.pecen = new_state;
- }
- /**
- * @brief get pec value.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @retval uint8_t: pec value.
- */
- uint8_t i2c_pec_value_get(i2c_type *i2c_x)
- {
- return i2c_x->sts2_bit.pecval;
- }
- /**
- * @brief enable or disable if the next dma transfer will be the last one.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_dma_end_transfer_set(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl2_bit.dmaend = new_state;
- }
- /**
- * @brief enable or disable dma requests.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_dma_enable(i2c_type *i2c_x, confirm_state new_state)
- {
- i2c_x->ctrl2_bit.dmaen = new_state;
- }
- /**
- * @brief enable or disable interrupt
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param source
- * this parameter can be one of the following values:
- * - I2C_DATA_INT: data interrupt.
- * - I2C_EV_INT: event interrupt.
- * - I2C_ERR_INT: error interrupt.
- * @param new_state (TRUE or FALSE)
- * @retval none
- */
- void i2c_interrupt_enable(i2c_type *i2c_x, uint16_t source, confirm_state new_state)
- {
- if (new_state != FALSE)
- {
- i2c_x->ctrl2 |= source;
- }
- else
- {
- i2c_x->ctrl2 &= (uint16_t)~source;
- }
- }
- /**
- * @brief generate start condition.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @retval none.
- */
- void i2c_start_generate(i2c_type *i2c_x)
- {
- i2c_x->ctrl1_bit.genstart = TRUE;
- }
- /**
- * @brief generate stop condition.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @retval none.
- */
- void i2c_stop_generate(i2c_type *i2c_x)
- {
- i2c_x->ctrl1_bit.genstop = TRUE;
- }
- /**
- * @brief transmit the slave address.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param address: specifies the slave address which will be transmitted
- * @param direction
- * this parameter can be one of the following values:
- * - I2C_DIRECTION_TRANSMIT: transmit mode.
- * - I2C_DIRECTION_RECEIVE: receive mode.
- * @retval none.
- */
- void i2c_7bit_address_send(i2c_type *i2c_x, uint8_t address, i2c_direction_type direction)
- {
- if(direction == I2C_DIRECTION_TRANSMIT)
- {
- i2c_x->dt = address & 0xFE;
- }
- else
- {
- i2c_x->dt = address | 0x01;
- }
- }
- /**
- * @brief send a byte through the i2c periph.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param data: byte to be transmitted.
- * @retval none
- */
- void i2c_data_send(i2c_type *i2c_x, uint8_t data)
- {
- i2c_x->dt = data;
- }
- /**
- * @brief receive a byte through the i2c periph.
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @retval uint8_t: received byte
- */
- uint8_t i2c_data_receive(i2c_type *i2c_x)
- {
- return (uint8_t)i2c_x->dt;
- }
- /**
- * @brief get flag status
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param flag
- * this parameter can be one of the following values:
- * - I2C_STARTF_FLAG: start condition generation complete flag.
- * - I2C_ADDR7F_FLAG: 0~7 bit address match flag.
- * - I2C_TDC_FLAG: transmit data complete flag.
- * - I2C_ADDRHF_FLAG: master 9~8 bit address header match flag.
- * - I2C_STOPF_FLAG: stop condition generation complete flag.
- * - I2C_RDBF_FLAG: receive data buffer full flag.
- * - I2C_TDBE_FLAG: transmit data buffer empty flag.
- * - I2C_BUSERR_FLAG: bus error flag.
- * - I2C_ARLOST_FLAG: arbitration lost flag.
- * - I2C_ACKFAIL_FLAG: acknowledge failure flag.
- * - I2C_OUF_FLAG: overflow or underflow flag.
- * - I2C_PECERR_FLAG: pec receive error flag.
- * - I2C_TMOUT_FLAG: smbus timeout flag.
- * - I2C_ALERTF_FLAG: smbus alert flag.
- * - I2C_TRMODE_FLAG: transmission mode.
- * - I2C_BUSYF_FLAG: bus busy flag transmission mode.
- * - I2C_DIRF_FLAG: transmission direction flag.
- * - I2C_GCADDRF_FLAG: general call address received flag.
- * - I2C_DEVADDRF_FLAG: smbus device address received flag.
- * - I2C_HOSTADDRF_FLAG: smbus host address received flag.
- * - I2C_ADDR2_FLAG: own address 2 received flag.
- * @retval flag_status (SET or RESET)
- */
- flag_status i2c_flag_get(i2c_type *i2c_x, uint32_t flag)
- {
- __IO uint32_t reg = 0, value = 0;
- reg = flag >> 28;
- flag &= (uint32_t)0x00FFFFFF;
- if(reg == 0)
- {
- value = i2c_x->sts1;
- }
- else
- {
- flag = (uint32_t)(flag >> 16);
- value = i2c_x->sts2;
- }
- if((value & flag) != (uint32_t)RESET)
- {
- return SET;
- }
- else
- {
- return RESET;
- }
- }
- /**
- * @brief clear flag status
- * @param i2c_x: to select the i2c peripheral.
- * this parameter can be one of the following values:
- * I2C1, I2C2.
- * @param flag
- * this parameter can be any combination of the following values:
- * - I2C_BUSERR_FLAG: bus error flag.
- * - I2C_ARLOST_FLAG: arbitration lost flag.
- * - I2C_ACKFAIL_FLAG: acknowledge failure flag.
- * - I2C_OUF_FLAG: overflow or underflow flag.
- * - I2C_PECERR_FLAG: pec receive error flag.
- * - I2C_TMOUT_FLAG: smbus timeout flag.
- * - I2C_ALERTF_FLAG: smbus alert flag.
- * @retval none
- */
- void i2c_flag_clear(i2c_type *i2c_x, uint32_t flag)
- {
- i2c_x->sts1 = (uint16_t)~(flag & (uint32_t)0x00FFFFFF);
- }
- /**
- * @}
- */
- #endif
- /**
- * @}
- */
- /**
- * @}
- */
|