Pin Multiplexing

Last Updated on : 2024-11-20 08:51:40

A number of the available pins can be used for multiple purposes other than the function they are intended to perform. Such pins are referred to as multiplexed pins. For example, the UART pins are multiplexed so that you can designate and use them as GPIO pins when needed.

This topic describes how to set a hardware pin to a specified mode without compromising its original function. We use the BT3L module as an example to illustrate how to change the function of your pins.

Method 1

Take the Telink as an example. To set the GPIO_PB1(UART TX) to operate in PWM mode, you need to initialize the UART after the device is powered on. If the device enters the test mode within one second, do not configure this pin as output. Otherwise, configure it as output.

  • Advantages: easy-to-configure and wide applicability.

  • Disadvantages: This method has no immediate effect. You have to wait for some time before pin configuration.

    //app.c
    
    uint32_t m_uart_muti_use_tick = 0;// Define a global variable
    
    void user_init_normal(void)
    {
    	……
    	uart_init(9600);
    	……
    	m_uart_muti_use_tick = clock_time();
    }
    
    
    void main_loop (void)
    {
    	static uint8_t PB1_init_flag =0;
    	////////////////////////////////////// BLE entry /////////////////////////////////
    	blt_sdk_main_loop();
    	
    	blt_soft_timer_process(MAINLOOP_ENTRY);
    
    
    	if(clock_time_exceed(uart_muti_use_tick,1000*1000))
    	{
    		//init 
    		if(PB1_init_flag==0)
    		{
    			PB1_init_flag = 1;
    			gpI/O_set_func(GPI/O_PB1, AS_PWM4);
    			pwm_set_mode(PWM4_ID, PWM_NORMAL_MODE);
    			pwm_set_phase(PWM4_ID, 0);   //no phase at pwm beginning
    			pwm_set_cycle_and_duty(PWM4_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US),  (u16) (667 * CLOCK_SYS_CLOCK_1US) );
    			pwm_start(PWM4_ID);
    		}
    	}
    	……
    }
    
    //……\tuya_ble_sdk\app\product_test\tuya_ble_app_productI/On_test.c
    
    /*********************************************************
    FN: Determine if the device enters the testing mode.
    */
    uint8_t tuya_ble_is_productI/On_test_effective(void)
    {
    	return tuya_ble_productI/On_test_flag;
    }
    

Method 2

Take the Telink as an example. To set the GPIO_PB1(UART TX) to operate in PWM mode, you need to configure this pin to PWM mode upon power on and scan for Bluetooth signals for one second. The UART initialization is started only after the module scans for the ty_prod packet.

  • Advantages: You can configure pins upon power on.

  • Disadvantages: The scanning feature and a Bluetooth beacon are required.

    //add ty_ble_scan_tlsr825x.c
    
    
    #include "tl_common.h"
    #include "stack/ble/gap/gap.h"
    #include "stack/ble/hci/hci_const.h"
    #include "stack\ble\ll\ll_scan.h"
    #include "stack\ble\ll\ll_whitelist.h"
    static char  m_ble_target_periph_name[8] = "ty_prod";
    typedef struct
    {
    	uint8_t     * p_data;    /**< Pointer to data. */
    	uint16_t      data_len;  /**< Length of data. */
    } data_t;
    
    uint32_t adv_report_parse(uint8_t type, data_t * p_advdata, data_t * p_typedata)
    {
    	uint32_t  index = 0;
    	uint8_t * p_data;
    	p_data = p_advdata->p_data;
    	while (index < p_advdata->data_len)
    	{
    		uint8_t field_length = p_data[index];
    		uint8_t field_type   = p_data[index + 1];
    
    		if (field_type == type)
    		{
    			p_typedata->p_data   = &p_data[index + 2];
    			p_typedata->data_len = field_length - 1;
    			return 0;//OPRT_OK
    		}
    		index += field_length + 1;
    	}
    	return 5;//OPRT_ERROR_NOT_FOUND
    }
    
    void tuya_ble_scan_evt_handler(uint32_t h, uint8_t *para, int n)
    {
    	event_adv_report_t *pa = (event_adv_report_t *)para;
    	int8_t rssi = pa->data[pa->len];
    	static uint8_t uart_init_flag = 0;
    	data_t adv_data;
    	data_t dev_name;
    	adv_data.p_data = pa->data;
    	adv_data.data_len = pa->len;
    
    	if(0 == adv_report_parse(GAP_ADTYPE_LOCAL_NAME_COMPLETE,&adv_data,&dev_name))
    	{
    		if(memcmp(m_ble_target_periph_name,dev_name.p_data,dev_name.data_len)==0)
    		{
    			if(uart_init_flag==0)
    			{
    				uart_init_flag = 1;
    				uart_init(9600);
    			}
    		}
    	}
    	else
    	{
    
    	}
    }
    extern int controller_event_handler(u32 h, u8 *para, int n);
    
    void tuya_ble_scan_init(void)
    {
    	//scan set
    	extern u8  mac_public[6];
    	blc_ll_initScanning_module(mac_public);		//scan module: 		 optI/Onal
    	blc_hci_le_setEventMask_cmd(HCI_LE_EVT_MASK_ADVERTISING_REPORT);
    	
    	//blc_hci_registerControllerEventHandler(tuya_ble_scan_evt_handler);		//register event callback
    	
    	blc_ll_setScanParameter(SCAN_TYPE_PASSIVE, SCAN_INTERVAL_30MS, SCAN_INTERVAL_30MS,
    									OWN_ADDRESS_PUBLIC, SCAN_FP_ALLOW_ADV_ANY);
    
    }
    uint8_t tuya_ble_scan_set_filter_name(char *bft_target_periph_name)
    {
    	memcpy(m_ble_target_periph_name,bft_target_periph_name,7);
    }
    void tuya_ble_scan_start(void)
    {
    	blc_hci_registerControllerEventHandler(tuya_ble_scan_evt_handler);		//register event callback
    	blc_ll_addScanningInAdvState();  //add scan in adv state
    	blc_ll_addScanningInConnSlaveRole();  //add scan in conn slave role
    	blc_ll_setScanEnable (1, 0);
    }
    void tuya_ble_scan_stop(void)
    {
    	blc_hci_registerControllerEventHandler(controller_event_handler);		//register event callback	
    	blc_ll_setScanEnable (0, 0);
    	blc_ll_removeScanningFromAdvState();
    	blc_ll_removeScanningFromConnSLaveRole();
    }
    
    
    
    
    //app.c
    
    tuya_ble_timer_t first_init_scan_timer;
    
    static void tuya_ble_first_init_scan_timeout_handler(tuya_ble_timer_t timer)
    {
    	tuya_ble_scan_stop();
    }
    void tuya_ble_first_init_scan_timer_start(void)
    {
    	static uint8_t init = 0;
    	tuya_ble_timer_create(&first_init_scan_timer,2000,TUYA_BLE_TIMER_SINGLE_SHOT,tuya_ble_first_init_scan_timeout_handler);
    	tuya_ble_timer_start(first_init_scan_timer);
    	if(init==0)
    	{
    		init = 1;
    		tuya_ble_scan_init();
    	}
    	tuya_ble_scan_start();
    }
    
    void user_init_normal(void)
    {
    	……
    	gpI/O_set_func(GPI/O_PB1, AS_PWM4);
    	pwm_set_mode(PWM4_ID, PWM_NORMAL_MODE);
    	pwm_set_phase(PWM4_ID, 0);   //no phase at pwm beginning
    	pwm_set_cycle_and_duty(PWM4_ID, (u16) (1000 * CLOCK_SYS_CLOCK_1US),  (u16) (667 * CLOCK_SYS_CLOCK_1US) );
    	pwm_start(PWM4_ID);
    
    	tuya_ble_first_init_scan_timer_start();
    }